For every one of the 10000 numbers in the sequence 0.000, 0.001, 0.002, 0.003 ... 9.999, the function:
scale x = round (1000*x)
will generate the "correct" four digit result. This is because any floating point error introduced by the expression 1000*x
will be a tiny fraction, on the order of 1e-13, so if the "correct" result of 1000*x
is -- say -- 1009, then the smallest possible answer you could get will be something like:
1008.9999999999999
and the largest possible answer you could get will be something like:
1009.0000000000001
Both of these integers are at least 10,000,000,000 times closer to 1009 than to any other integer, and since round
rounds to the closest integer, it will always round to the correct answer.
Note that floor
and ceiling
are entirely different. They do not round to the closest integer, but rather to the closest integer in a particular direction, so they can clearly give the wrong answer. Specifically, they can give:
floor 1008.9999999999999 == 1008 -- wrong!
ceiling 1009.0000000000001 == 1010 -- wrong!
Scaling using round
will work for larger scalings as well, to a point -- specifically, to the point where the scaling is around 1e16. Where the scaling is "only" 1e15, the transformation still works (for all x
in the above sequence):
scale x = round (1000000000000000*x)
But, when the scaling is 1e16:
scale x = round (10000000000000000*x)
you start to get wrong answers:
ghci> scale 0.5005
5004999999999999
If you want to get correct answers for all scalings, then do the scaling in two parts:
scale :: RealFrac n => n -> Integer
scale x = 10000000000000000000000000000000000 * round (10000*x)
Here, the expression round (10000*x)
reliably scales any number from the sequence 0.000, 0.001, ..., 9.999 to the corresponding integer from the sequence 0, 1, ..., 9999 without the possibility of a floating point error, as explained above. From there, arbitrary precision Integer
multiplication by any integer, no matter how large, will be error-free.