displaydisplayname
displaydisplayname

Reputation: 317

Does a hardcode float num a.bc... (0<=n<100 decimals,MIN_VALUE<=a.bc...<=MAX_VALUE) always equals to Number.parseFloat((a.bc...).toFixed(n))?

For example, I know 0.12,ie:

const a=0.12;

rounds to something due to float number errors. However, I'm not asking why the error happens and I don't care the errors currently, instead I want to know if the hardcode form always equals to the value after adding toFixed following Number.parseFloat.

Consider the following:

console.log(0.12 == Number.parseFloat(0.12.toFixed(2)));
console.log(987.123 == Number.parseFloat(987.123.toFixed(3)));
console.log(98765.12345678 == Number.parseFloat(98765.12345678.toFixed(8)));

the hardcode values above equals to the value after adding toFixed(n) and Number.parseFloat.

However, I don't know if other cases are also true. So my question is, for a float number a.bc... with n decimals 0-100 and value between MIN_VALUE and MAX_VALUE, does its original hardcode form rounds to the value always the same as Number.parseFloat(a.bc.toFixed(n)) ? ie:

console.log(a.bc... == Number.parseFloat((a.bc...).toFixed(n))); //"bc..." means n decimals, 0 <= n <= 100 , MIN_VALUE <= a.bc <= MAX_VALUE

does the code above always true? If it does, does it also true for -a.bc..? And if it doesn't, what is the reason?

Upvotes: 4

Views: 106

Answers (1)

Pointy
Pointy

Reputation: 413717

Parsing the string after .toFixed(2), which will be the string "0.12", will result in exactly the same (possibly imprecise) value that you started out with. Basically parseFloat() does the same thing the JavaScript interpreter does with numeric constants in the source code.

... except that parseFloat() will ignore non-numeric garbage after the numeric part, but in this case that's not relevant.

Pretty much all the interpreter and the runtime can do is iterate through the characters of the numeric string, dividing by inverse powers of ten (after the decimal point) and adding up to an accumulator value. The floating-point math involved is all the same. Before the decimal point, you grab a digit, multiply the accumulator by 10, and add the digit value. After the decimal point, you grab the digit, multiply it by a negative power of 10, and again add to the accumulator.

Now, I don't think this is what your question is about, but if you have code like

const a = 0.1213;
const b = a.toFixed(2);
const c = parseFloat(b);

then you will definitely end up with a different value because the .toFixed() call is throwing digits away.

Oh and one more thing: all of the above is true, but in real code when you're comparing fractional numbers, you have to take into account the nature of your application and the math it requires and come up with an "epsilon"-based comparison to use. That is, you have to decide what it means for two floating-point values possibly computed along independent paths to be considered "equal". There's no one answer to this; for example, in a game the details of the "world" geometry would have a lot to do with deciding whether 0.00012 and 0.00011 are "equal". Maybe they are, maybe they aren't, but the point is that absolute equality in software based on floating-point math is just not going to work.

Upvotes: 3

Related Questions