Hiddin
Hiddin

Reputation: 75

How to count from 0.0001 to 1 in ruby?

I want to count from 0.0001 to 1 with 0.0001 steps in ruby. I wrote this code but it enters to an infinite loop. Somewhy the interpreter does a wrong summation.

x = 0.0001
while x != 1.0
  puts x
  x = x + 0.0001
end

Here is the first 10 value it gives:

0.0001
0.0002
0.00030000000000000003
0.0004
0.0005
0.0006000000000000001
0.0007000000000000001
0.0008000000000000001
0.0009000000000000002
0.0010000000000000002

It should be 0.0001, 0.0002, 0.0003, etc... How can I make it working? Thanks!

Upvotes: 7

Views: 607

Answers (6)

Marek Příhoda
Marek Příhoda

Reputation: 11198

1.step(10000, 1).each { |x| puts "%f" % (x / 10000.0).round(4) }

Upvotes: 0

gioele
gioele

Reputation: 10205

Try this:

0.0001.step(1, 0.0001).each { |i| puts i }

EDIT: you should use the Float#step method because it shields you from the weirdness of float arithmetic. Float#step will take care of incrementing the value and comparing to the limit in a float-proof way. For more information have a look at the official documentation of Float#step.

Upvotes: 16

Mark Thomas
Mark Thomas

Reputation: 37517

What you are seeing is due to binary representation of floating-point numbers. This affects all computer programming languages. For more detail see What Every Computer Scientist Should Know about Floating Point Arithmetic.

What you can do is round it to the appropriate number of digits at print time, or as goiele has found, use step:

0.0001.step(1, 0.0001).each do |i|
  puts i
end

Upvotes: 0

Tom Cerul
Tom Cerul

Reputation: 1953

Floating point numbers are not exactly accurate Wikipedia Floating Point article.

If you must have clean x's, I'd recommend using an integer and dividing down by 1000 before you use the value. If you don't care about the little bits of noise off, you'll be fine with changing your while x != 1.0 to while x < 1.0

Upvotes: 0

ghoppe
ghoppe

Reputation: 21794

The problem is that real numbers in ruby are not represented exactly due to binary storage and manipulation. I would do this

x = 1
while x < 10000
    puts (x/10000).round(4)
    x += 1
end

Upvotes: 2

cdeszaq
cdeszaq

Reputation: 31290

Rather than x != 1.0, put x < 1.0. That will at least be sure your loop ends.

A binary system like those that run all of our modern computers cannot (easily) represent fractions, especially ones that cannot be accurately represented in decimal. That is where the strange number comes in when you should have .0003. It is an artifact of how the numbers are represented internally.

Some languages are better at dealing with numbers and accuracy than others, so if the accuracy of the numbers matters, you either need to use a different language, use a library that handles the number things for you (significant digits and all that), or you need to handle it yourself with appropriate rounding, etc. at each step.

Upvotes: 1

Related Questions