Reputation: 8631
Would scaling a float value by ten to preserve precision during a calculation be always precise?
This question only applies for any number involved being less than Math.pow (2,53)
and greater than Math.pow (10,-15)
, as Math.pow (10,16 ) > Math.pow (2,53)
I hope this clears some points
0.3 - 0.2 //0.09999999999999998
Is obvious unprecise
But doing the substraction on a scaled number
var a = 0.3;
var b = 0.2;
var l = Math.max ("".split.call(a,".")[1].length,"".split.call(b,".")[1].length);
var c;
a *= Math.pow (10,l);
b *= Math.pow (10,l);
c = a-b;
c /= Math.pow(10,l);
console.log(c); //0.1
Gives a " precise " result.
The Question is, is there any float value, matching the above mentioned criterias f<Math.pow(10,-15)
,when multiplied by a power of ten (where Math.pow ( 10 , n<16)<Math.pow(2,53)
), which does not result in the double value nearest
N(b)-N(a)?, when divided again by the same power of 10?
Like described in the snippet above.
This is only a question of interest, not about using this for actual calculations, I'm just curious
And sry for misunderstandings I`m not good in this Explanation thingy
Upvotes: 4
Views: 386
Reputation: 223389
I believe the intent of the question is misdirected.
If you have some binary floating-point values a and b that you know are very near decimal numerals with a few digits, then multiplying those values by a power of ten, subtracting, and dividing by the power of ten generally does not provide a better result than simply subtracting the values directly. Each of the multiplications and divisions often introduces some rounding error, and these tend to make the final result less accurate than simply subtracting a and b directly. Thus, nothing is gained by using this roundabout method.
Since a and b already have some rounding errors (they are not exactly the numerals they are near, and it is those numerals you desire to represent), sometimes the calculated value b-a
will not be the floating-point value that is nearest the difference of the decimal numerals (but it will be at most one ULP away). Infrequently, the combinations of the rounding errors in the detoured calculation will provide a result closer to that difference, but that is more a matter of happenstance (effectively chance) than of design.
Once you know the power of 10 involved, p, you could get this best possible result by calculating Math.round((b-a)*p)/p
, provided the numbers involved are sufficiently small that the rounding error in (b-a)*p
is always less than .5.
Regardless, it is likely neither approach is a good way to design your calculations.
Regarding Edit3: All non-negative powers of ten less than 253 are representable exactly. A proper pow
implementation returns exact results for these cases. Consider a double x in which the lowest bit set has value 2–d. The least power of ten that produces an integer when multiplied by this double is 10d. If 10d is less than 253 and 10d•x is less than 253, then both are exactly representable. Then by the IEEE-754 specification of floating-point arithmetic, the product of 10d and x is exact.
Upvotes: 1