Reputation: 7080
I understand about Number.MAX_SAFE_INTEGER
and Number.MIN_SAFE_INTEGER
.
I understand that Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
equals true.
But I've only recently realised that:
var number = 2007199254740991;
var float = 2007199254740991.123;
console.log(number === float);
// => true
But
var number = 1007199254740991;
var float = 1007199254740991.123;
console.log(number === float);
// => false
So my question is, how do we find the "max safe float"?
EDIT
My question:
At what point does comparing between an "integer" and a "float" equals true
?
Upvotes: 1
Views: 144
Reputation: 222933
Asking when comparing fails is the wrong question. Comparing two numbers always works correctly; it evaluates to true if and only if the two numbers being compared have the same value.
The problem actually occurs in earlier operations. Converting a numeral in source code to a Number
, adding numbers, and other operations introduce errors when the exact real-number mathematical value is rounded to a value representable in floating-point.
JavaScript uses IEEE-754 binary64, which has a 53-bit significand (the fraction portion of a floating-point number). This means any number with a magnitude of 252 or greater does not have any bits that can represent values less than 1—they have no fraction portion. So, when any number 252 or greater is converted to a JavaScript Number
, the result is an integer.
But smaller numbers are rounded too. From 251 to 252, the least significant bit available represents 2−1, or ½. So any number in this interval that is converted to a Number
must produce either an integer or an integer plus ½. That means some numbers, like 2251799813685248.6, will produce non-integers (2251799813685248.5), while others, like 2251799813685248.8 will produce integers (2251799813685249).
At every magnitude below 252, there are some numbers that will be rounded to integers when converted to Number
and some numbers that will not be rounded to integers. (Above 252, all numbers are rounded to integers.) At smaller magnitudes, only numbers closer to integers are rounded to integers—the format becomes more “sensitive” as the magnitude decreases.
Upvotes: 3
Reputation: 424
You can't find a "max safe float" in JavaScript. It simply doesn't exist.
@CertainPerformance is right, there's a limited precision in JS. Besides, remember that a number in a programming language is stored by 0 or 1 bits, and remember that you can have infinite decimals, so... can you have infinite 0's and 1's? .
As any computer can store infinite numbers, there's no max safe float number.
Upvotes: 0
Reputation: 370819
There is no such thing, because Javascript numbers have limited precision, or significant digits (effectively).
const n1 = 1e-10;
const n2 = 1e-30;
console.log(n1 - n2 === n1);
Even a very small number like 1e-10
will have imprecise behavior when manipulated in combination with numbers significantly smaller than it. The same sort of thing is happening with your snippet - ~1e15
(close to the value of your 1007199254740991
) is too large in comparison to 0.123
.
There's also the famous imprecise 0.1 + 0.2:
console.log(0.1 + 0.2);
In addition to significant digits being effectively limited, numbers which cannot be precisely represented in binary will have this sort of problem.
Upvotes: 3