From: Tanaka Akira Date: 2013-04-05T11:02:13+09:00 Subject: [ruby-core:54008] Re: [ruby-trunk - Bug #7829] Rounding error in Ruby Time 2013/4/5 David MacMahon : > Of course you're right about String#to_r being correct. I think Float#to_s is correct as well. I think the problem is actually in Rational#to_f. It is expected that Rational#to_f can error because Float has only 53bit mantissa but Rational can hold more digits. (Ruby uses double type in C and it is usally IEEE 754 double which has 53bit mantissa.) > Each distinct Float value has (or should have, IMHO) an unambiguous String representation such that f.to_s.to_f == f, discounting NaN and Infinity for which this relationship doesn't hold due to a limitation (bug?) of String#to_f. > > String#to_r works correctly as you pointed out. > > The problem occurs because the Rational returned by String#to_r is reduced. When converting the reduced fraction of this example to Float, Rational#to_f effectively computes: > >>> 11512646564871409.to_f/200000000000.to_f > => 57563.23282435704 <=== does NOT equal original value Float cannot represent 11512646564871409 exactly. % ruby -e 'i = 11512646564871409; p i.to_s(2), i.to_s(2).length' "101000111001101011000011101000111011000111110011110001" 54 The result is just an (good) approximation. > instead of the un-reduced computation of: > >>> 57563232824357045.to_f/1000000000000.to_f > => 57563.232824357045 <=== DOES equal original value Float cannot represent 57563232824357045 exactly, too. % ruby -e 'i = 57563232824357045; p i.to_s(2), i.to_s(2).length' "11001100100000010111010010001100100111100111000010110101" 56 The equality is just a luck. There are 7 integers to print 57563.232824357045. % ruby -e '-7.upto(7) {|off| p((57563232824357045+off).to_f/1000000000000.to_f) }' 57563.23282435704 57563.23282435704 57563.23282435704 57563.23282435704 57563.23282435704 57563.23282435704 57563.23282435704 57563.232824357045 57563.232824357045 57563.232824357045 57563.232824357045 57563.232824357045 57563.232824357045 57563.232824357045 57563.23282435706 It seems your requirement is too strong for Float. -- Tanaka Akira