Issue #5273 has been updated by Yui NARUSE.

Status changed from Open to Assigned
Assignee set to Marc-Andre Lafortune

Marc-Andre Lafortune wrote:
> I'm not sure, are you trying to be rude or irritating by rejecting for a second time this issue in this way?
> 
> If so, please stop.

Ah sorry, I intended to close this ticket without comment.
"r33186" is wrong comment.
(though r33186 is not valid ruby -v, you must copy and paste full `ruby -v` output)

> If not, would you be kind enough to explain the following:
> - What makes you believe r33186/issue #5272 is related with this issue #5273?
> - Why do I have to repeat [ruby-core:39296] that issues #5272 and #5273 are not related?
> - Why do you think I opened two different issues in the first place (and fixed only one of them)?
> - Is there anything in the examples given in the two issues, or in the specs I wrote that makes it possible to confuse both issues?
> - Why do you feel it is appropriate to reject this issue by simply referring to one of my commits, without any explanation whatsoever?
> - Don't you feel that even if the commit addressed the issue, the issue should have been Closed, not Rejected?

Yeah, #5272 and #5273 are different.
#5272 is truely a bug of ruby, but #5273 is not.

> In addition, may I ask that you do not reject this issue a third time? I will set it myself to rejected if a compelling reason is given. Note that "Use BigDecimal" is not such a reason. Nor is `3.0/10**31 == 3.0000000000000003e-31`. Indeed, why stop there, why not have `Float("3.0e-31") == 3.0000000000000003e-31` and invoque the same arguments?

I can't your English of this line, I think you are saying you can't understand [ruby-core:39443].
I add little more explanation.

First of all, ISO C doesn't specify the detail of floating point numbers.
So my discussion of this comment follows IEEE 754 non x87 floating point numbers.

IEEE 754 double (binary64) is sign 1bit, exponent 11bit, and fraction 52bit,
and its internal reprensentation is binary (not decimal).
When a number is converted to float, the number's precision is limited to this and
lost information over decimal/binary conversion.

For example, 3.0 / 10**31 is considered as 3.0 * 1.0e-31 (this is not accurate).
This is 3.0 * 0.000000000000000000000000000000100000000000000008333642060759
It become 0.000000000000000000000000000000300000000000000025000926182276.
If you show this by inspect, it is rounded and showed as 3.0000000000000003e-31.
And it is a different number from 3.0e-31 in Float.


If you use BigDecimal, such binary/decimal conversion is not done and you can specify its precision.
So you can get expected result:
  irb(main):092:0> BigDecimal("2.5e-31").round(31).to_s
  => "0.3E-30"

If you are still hard to understand my explaration, I doubt you don't understand floating point numbers.
If so, please read following documents.
http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
http://wiki.github.com/rdp/ruby_tutorials_core/ruby-talk-faq#floats_imprecise
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

I assign this ticket to you, please close this after you understand.
----------------------------------------
Bug #5273: Float#round returns the wrong floats for higher precision
http://redmine.ruby-lang.org/issues/5273

Author: Marc-Andre Lafortune
Status: Assigned
Priority: Normal
Assignee: Marc-Andre Lafortune
Category: core
Target version: 1.9.4
ruby -v: r33186


Float#round returns the wrong floats for higher precision.

Rounding can be off:
    2.5e-22.round(22) # => 2.0e-22

It can also return values that have extra decimals:
    2.5e-31.round(31) # => 3.0000000000000003e-31
    2.5e-36.round(36) # => 2.9999999999999998e-36

Both errors can occur at the same time too:
2.5e-39.round(39) # => 2.0000000000000002e-39

I believe these errors occur only for ndigits >= 22. For ndigits > 22, 10**(-ndigits) is not an exact Float (as 5 ** 23 won't fit in the 53 bits of a double's mantissa). For ndigits < 22, there should be enough bits left to avoid rounding errors.

For ndigits >= 22, the algorithm to use should be similar to the one used to convert doubles to string.

Hopefully, this is the last bug for #round with a given precision.


-- 
http://redmine.ruby-lang.org