Search code examples
rubyarraysfloating-pointenumerable

Generating an array of floats produces a weird result


I want to generate an array of float. For instance, this one:

[0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]

So, I use this tiny line:

(0.5..2).step(0.1).to_a

But it produces this instead:

[0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2000000000000002, 1.3, 1.4, 1.5, 1.6, 1.7000000000000002, 1.8, 1.9000000000000001, 2.0]

What have I done wrong?


Solution

  • Use Rational Literals, Then Map to Floats

    Floating point numbers can bite you. Specifically, binary can't represent 0.1 accurately. Ruby has a number of classes for dealing accurately with arbitrary-precision numbers, including BigDecimal and Rational.

    You can use the new 2.1 syntax for rational literals to create your series of floats. For example:

    (0.5r..2r).step(0.1r).map &:to_f
    #=> [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
    

    Doing it this way may look a little more cluttered than the currently-accepted answer, but this approach is applicable to a wider range of precision problems where dividing by 10.0 is not the solution.