Possible Duplicate:
Haskell ranges and floats
For example, when I type
[0.1, 0.3 ..1]
I get this:
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
I expected:
[0.1,0.3,0.5,0.7,0.9]
Possible Duplicate:
Haskell ranges and floats
For example, when I type
[0.1, 0.3 ..1]
I get this:
[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
I expected:
[0.1,0.3,0.5,0.7,0.9]
Try
map (/10) [1, 3 .. 10]
instead.
The problem is that floating point numbers use binary fractions, and binary fractions can't exactly represent decimal fractions. So you get errors and the errors build up.
A binary fraction cannot exactly represent 1/5 in the same way that a decimal fraction cannot exactly represent 1/3 --- the best we can do is 0.33333....
[0.1, 0.3 .. 1]
is shorthand for
[0.1,
0.1 + 0.2,
0.1 + 0.2 + 0.2,
0.1 + 0.2 + 0.2 + 0.2,
0.1 + 0.2 + 0.2 + 0.2 + 0.2,
0.1 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2]
The other problem is that the list will stop after the first element that is equal to or past the limit when the next element would be more than half the step past the limit, which is why you have the 1.0999999999999999
element.
This is an issue with how floating point numbers are represented in the computer. Simple arithmetic with floating point numbers often does not behave as expected. Repeated arithmetic can accumulate "rounding error", which means the result can get progressively worse as you repeatedly add numbers (for example).
You can avoid these problems in some cases by using a different numerical representation. If you only care about rational numbers, for example, you could use the Rational
type. So you could do:
[0.1,0.3..1] :: [Rational]
which results in:
[1 % 10,3 % 10,1 % 2,7 % 10,9 % 10,11 % 10]
This is the correct answer with no rounding error; each number is just represented as the ratio of two Integer
s. Depending on your particular situation, this may be a better option than using floating point numbers.
This does still go over the upper bound, but that is much easier to deal with than the rounding error you get from floating point numbers.
Note that for something performance critical floating point numbers are probably going to be faster.
The expression [e1, e2 .. e3]
is evaluated as enumFromThenTo e1 e2 e3
, which for floating point numbers means (from The Haskell 98 Report):
For Float and Double, the semantics of the enumFrom family is given by the rules for Int above, except that the list terminates when the elements become greater than
e3+i/2
for positive increment i, or when they become less thane3+i/2
for negative i.
This means that with floating point numbers the last element of [e1, e2 .. e3]
is often greater than e3
, and can be up to e3+(e2-e1)/2 - ε
.