Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two numbers in JavaScript, what about the fact those are doubles and the use of == or ===?

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

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

11.9.6 The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false. Such a comparison 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 comes to comparing 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++.

like image 366
Alexis Wilke Avatar asked Sep 30 '22 17:09

Alexis Wilke


1 Answers

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

When comparing 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 common 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 complicated. 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.

like image 95
Ryan Avatar answered Oct 05 '22 11:10

Ryan