yqlim
yqlim

Reputation: 7080

At what point does comparing between an "integer" and a "float" equals `true`?

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

Answers (3)

Eric Postpischil
Eric Postpischil

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

xale94
xale94

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

CertainPerformance
CertainPerformance

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

Related Questions