0
1.824999999999999.round(2) # => 1.82 1.82499999999999999.round(2) # => 1.83 

I don't understand why the result in the first case is 1.82 and for the latter 1.83. My desired result is 1.82 for both cases.

1

4 Answers 4

6

As is well known, a floating number in computer has errors. Notice that both numbers that you have are close to 1.825. In your first case, the number is small enough to be differentiated from 1.825.

1.824999999999999 # => 1.824999999999999 

In your second case, having enough 9s makes the value close enough to be considered exactly as 1.825:

1.82499999999999999 # => 1.825 

Then, when you apply round, you get 1.83.

Sign up to request clarification or add additional context in comments.

Comments

3

In addition to the many excellent explanations here, I'd like to give an example using BigDecimal

o = BigDecimal.new('1.82499999999999999', 17) 2.0.0p247 :011 > o.round(2).to_f => 1.82 

Also notice that #round takes various modes for rounding, as per the docs.

Ref:

  1. http://www.ruby-doc.org/stdlib-2.1.0/libdoc/bigdecimal/rdoc/BigDecimal.html#method-c-mode
  2. http://www.ruby-doc.org/stdlib-2.1.0/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-round

Comments

3

After a certain number of (binary) digits, Ruby cannot represent differences between Float literals, even if you've entered the value directly in source code or the console

 1.82499999999999999 == 1.825 # => true 

If you really need a high level of precision, then you could look at the BigDecimal class. Although you could still enter enough 9s to reach limits in that class.

Comments

2

Floats are notoriously imprecise as sawa and Neil have pointed out.

If this is mainly an issue for testing, you can use assert_in_delta if you're using minitest, or be_within with rSpec

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.