admin管理员组

文章数量:1391818

When I write code in JavaScript, I rarely think about the consequence of using the == or === operators while paring numbers. However, JavaScript numbers are double's and as such the == and === should never be used as is.

From the documentation on paring two numbers with === we get:

11.9.6 The Strict Equality Comparison Algorithm

The parison x === y, where x and y are values, produces true or false. Such a parison is performed as follows:

  1. If Type(x) is different from Type(y), return false.

  2. If Type(x) is Undefined, return true.

  3. If Type(x) is Null, return true.

  4. If Type(x) is Number, then

    a. If x is NaN, return false.

    b. If y is NaN, return false.

    c. If x is the same Number value as y, return true.

    d. If x is +0 and y is -0, return true.

    e. If x is -0 and y is +0, return true.

    f. Return false.

  5. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.

  6. If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
  7. Return true if x and y refer to the same object. Otherwise, return false.

NOTE This algorithm differs from the SameValue Algorithm (9.12) in its treatment of signed zeroes and NaNs.

The non strict == operator has the same algorithm when it es to paring two numbers (4.a to 4.f), only it allows for the conversion of strings to a number.

So... is the language intrinsically testing floating points with a certain precision or do they use the plain good old == as found in C/C++ and other languages?

var a = 1.23;
    b = 1.230000001;

if(a === b) alert("equal?!");

This code does not produce the alert which would mean that it works as in C/C++.

When I write code in JavaScript, I rarely think about the consequence of using the == or === operators while paring numbers. However, JavaScript numbers are double's and as such the == and === should never be used as is.

From the documentation on paring two numbers with === we get:

11.9.6 The Strict Equality Comparison Algorithm

The parison x === y, where x and y are values, produces true or false. Such a parison is performed as follows:

  1. If Type(x) is different from Type(y), return false.

  2. If Type(x) is Undefined, return true.

  3. If Type(x) is Null, return true.

  4. If Type(x) is Number, then

    a. If x is NaN, return false.

    b. If y is NaN, return false.

    c. If x is the same Number value as y, return true.

    d. If x is +0 and y is -0, return true.

    e. If x is -0 and y is +0, return true.

    f. Return false.

  5. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.

  6. If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
  7. Return true if x and y refer to the same object. Otherwise, return false.

NOTE This algorithm differs from the SameValue Algorithm (9.12) in its treatment of signed zeroes and NaNs.

The non strict == operator has the same algorithm when it es to paring two numbers (4.a to 4.f), only it allows for the conversion of strings to a number.

So... is the language intrinsically testing floating points with a certain precision or do they use the plain good old == as found in C/C++ and other languages?

var a = 1.23;
    b = 1.230000001;

if(a === b) alert("equal?!");

This code does not produce the alert which would mean that it works as in C/C++.

Share Improve this question asked May 24, 2014 at 3:23 Alexis WilkeAlexis Wilke 20.9k11 gold badges106 silver badges179 bronze badges 6
  • 6 It is rarely ever valid to test floating point numbers for equality (zero being an exception). – Jonathon Reinhart Commented May 24, 2014 at 3:25
  • 1 Floating point equality is a bit-for-bit parison, whether you're doing it with == or ===. Really, your question isn't super clear here. (The +/- zero case is clearly an exception to the bit-for-bit thing, but that's just one bit :) – Pointy Commented May 24, 2014 at 3:30
  • If you want to pare two floats for equality in javascript (or even in C++), you pretty have to round it to a specific precision and if they are the same type, it makes no difference whether you use == or ===. – jfriend00 Commented May 24, 2014 at 3:30
  • My question is about numbers in general. In JavaScript, we all do stuff such as if(counter == 5) ... yet counter is a double (internally). So I was wondering whether there was some heuristic in JavaScript to make sure such tests work as expected. – Alexis Wilke Commented May 24, 2014 at 3:35
  • What about using if(parseInt(counter, 10) === 5)? – Shakeel Commented May 24, 2014 at 3:45
 |  Show 1 more ment

1 Answer 1

Reset to default 4

As you found, == and === behave identically if both types are numbers.

When paring numbers for equality, JavaScript obeys the IEEE 754 standard. For most purposes, this is no different than C's double type. It means JavaScript will not do any precision checks for you. When needed, you write your own code to handle precision loss.


That answers your question, but there is one very mon misconception you brought up!

JavaScript numbers are double's and as such the == and === should never be used as is.

The actual math behind this is a bit more plicated. Once grasped, you get some leeway with precision checks.

Consider the following which are guaranteed truths:

5 + 6 === 11
3 + 0.5 === 3.5
1.1 + 1 === 2.1
1.230000001 === 1.230000001
40 / 2 === 20
-0 === +0

But still, the following could be true or false depending on precision:

1.23 === 1.230000001
1.1 + 0.1 === 1.2
11 / 10 * 11 === 11 * 11 / 10

To make dealing with doubles easier, these conditions will not cause a loss of precision for a large range of floating-point numbers:

  • Adding, subtracting and multiplying doubles without a fractional part
  • Dividing doubles without a fractional part and that are divisible
  • Adding together doubles which are represented as a fraction of denominator 2, 4, 8, 16, ...
  • Multiplying any double by 0, 1, -1, 2, -2, 4, -4, 8, -8, ...
  • Dividing any double by 1, -1, 2, -2, 4, -4, 8, -8, ...

Finally, if you want to know more about floating-point math, this article is heavily referenced (but may go into too much detail for your needs): What Every Computer Scientist Should Know About Floating-Point Arithmetic.

本文标签: