Okay so I've read few things about this topic :
How to deal with floating point number precision in JavaScript?
Is floating point math broken?
Why can't decimal numbers be represented exactly in binary?
My question isn't why it's happening, or how to solve it.
It's about if there is a way to predict that it will happen, and then use a solution only if it'll happen. And more than just this, I'd like a low computation cost solution.
I ran few tests, and I feel like there are conditions required for this kind of problem to happen, but I'm not sure about them :
console.log("1st calc", parseFloat(-24.05) + parseFloat(24.05));
console.log("2nd calc", parseFloat(-12.003) + parseFloat(12.003) + parseFloat(-24.05) + parseFloat(24.05));
console.log("3rd calc", parseFloat(-12.003) + parseFloat(-24.05) + parseFloat(12.003) + parseFloat(24.05));
console.log("4th calc", parseFloat(12.003) + parseFloat(24.05) + parseFloat(-12.003) + parseFloat(-24.05));
console.log("5th calc", parseFloat(12.006) + parseFloat(-12.006) + parseFloat(2.007) + parseFloat(-2.007) + parseFloat(1.009) + parseFloat(-1.009));
console.log("6th calc", parseFloat(12.006) + parseFloat(2.007) + parseFloat(1.009) + parseFloat(-12.006) + parseFloat(-2.007) + parseFloat(-1.009));
console.log("7th calc", parseFloat(12.05) + parseFloat(2.003) + parseFloat(1.005) + parseFloat(7.01) + parseFloat(-12.05) + parseFloat(-2.003) + parseFloat(-1.005) + parseFloat(-7.01));
console.log("8th calc", parseFloat(12.05) + parseFloat(-12.05) + parseFloat(2.003) + parseFloat(-2.003) + parseFloat(1.005) + parseFloat(-1.005) + parseFloat(7.01) + parseFloat(-7.01));
I got it that it's about whether the number has an exact binary representation or not, but to know this it's a long computation, so is there a faster/easier way to predict it or not ?
The thing is, I'd like to have a script that tests if it has an exact binary representation or not, and then apply a solution only if needed. But I'd like it to be faster than just apply the solution to every float. I don't know if it's possible.
Something like
def power_of_2?(number)
return true if number == 1
return false if number == 0 || number % 2 != 0
power_of_2?(number / 2)
end
Might help to know wether the number has an exact binary representation, but I'm not even sure it's accurate enough for numbers such as 1.300005407.
For example, using the numbers I wrote in the tests above, I feel like it's faster to multiply them all by 1000 inside the parseFloat() (which solves the problem here) than testing them one by one.
Something I noticed too with my tests, is that according to the way you add the numbers, the problem occurs or not :
console.log("7th calc", parseFloat(12.05) + parseFloat(2.003) + parseFloat(1.005) + parseFloat(7.01) + parseFloat(-12.05) + parseFloat(-2.003) + parseFloat(-1.005) + parseFloat(-7.01));
console.log("8th calc", parseFloat(12.05) + parseFloat(-12.05) + parseFloat(2.003) + parseFloat(-2.003) + parseFloat(1.005) + parseFloat(-1.005) + parseFloat(7.01) + parseFloat(-7.01));
uses the same numbers, just not in the same order and give a totally different result.
Any idea ?