Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Haskell, [0.1..1] returns [0.1,1.1]. Why? [duplicate]

Tags:

list

haskell

I am finding the list of [0.1..1] that will be returned from Haskell and I do not understand why it is [0.1,1.1]. Can anyone provide explanation for me please?

like image 203
renW Avatar asked Oct 06 '21 11:10

renW


1 Answers

TL;DR: don't use [x..y] on floating point numbers. You might get unexpected results.

On floating point numbers, there's no sane semantics for [x..y]. For instance, one might argue that the semantics should be [x,x+1,x+2,...,x+n] where x+n is the largest value of that form which is <=y. However, this does not account for floating point rounding errors. It is possible that x+n produces a slightly larger value than the exact y, making the list shorter than expected. Hence this semantics makes the value of length [x..y] rather unpredictable.

Haskell tries to mitigate this issue, by allowing an error up to 0.5. The rationale is as follows: when x+n is closer to y than to y+1, it should be regarded as some value in the interval [x..y] which got rounded to something larger. Arguable, but this is how Haskell works.

In enumerations like [x,y .. z] with an explicit stepping (e.g. [0.0,5.0 .. 1000.0]) Haskell instead allows an error of (y-x)/2 (2.5 in the example). The rationale is the same: we include those points which are closer to 1000 than to 1000+5.

You can find all the gory details in the Haskell Report which defines the semantics of Haskell. This part is also relevant.

This is generally seen by Haskellers as a small wart in the language. Some argue that we should not have mandated Enum Float and Enum Double. Removing those instances would effectively prohibit the troublesome cases like [1.0 .. 5.0] or the much worse [1.0 .. 5.5] (which is again numerically unstable).

like image 147
chi Avatar answered Nov 18 '22 20:11

chi