From: "mame (Yusuke Endoh)" Date: 2013-02-19T00:35:32+09:00 Subject: [ruby-core:52476] [ruby-trunk - Bug #7458] Depending on value of BigDecimal::limit, addition can give inaccurate results Issue #7458 has been updated by mame (Yusuke Endoh). Target version changed from 2.0.0 to next minor ---------------------------------------- Bug #7458: Depending on value of BigDecimal::limit, addition can give inaccurate results https://bugs.ruby-lang.org/issues/7458#change-36546 Author: bpow (Bradford Powell) Status: Assigned Priority: Normal Assignee: mrkn (Kenta Murata) Category: ext Target version: next minor ruby -v: 2.0.0dev =begin This bug is present in ruby-trunk and also in 1.8.7 and 1.9.3p125. I apologize that I cannot figure out what exactly is going wrong and how to patch, but at least I have a small reproducible test case. When adding very small numbers (like 7E-19) to 1, the result should be very close to 1. However, depending on the limit to BigDecimal's precision, this is not always what is resulted, as this script demonstrates: require 'bigdecimal' one = BigDecimal('1') smallnum = BigDecimal('7E-19') 0.upto(20) do |lim| BigDecimal::limit(lim) result = one + smallnum puts "result is #{result}, as float is #{result.to_f} with limit #{lim}" end When run in trunk (or 1.8.7), the results it gives are: result is 0.10000000000000000007E1, as float is 1.0 with limit 0 result is 0.1E1, as float is 1.0 with limit 1 result is 0.1E1, as float is 1.0 with limit 2 result is 0.1E1, as float is 1.0 with limit 3 result is 0.1E1, as float is 1.0 with limit 4 result is 0.1E1, as float is 1.0 with limit 5 result is 0.1E1, as float is 1.0 with limit 6 result is 0.1E1, as float is 1.0 with limit 7 result is 0.1E1, as float is 1.0 with limit 8 result is 0.1E1, as float is 1.0 with limit 9 result is 0.2E1, as float is 2.0 with limit 10 result is 0.2E1, as float is 2.0 with limit 11 result is 0.2E1, as float is 2.0 with limit 12 result is 0.2E1, as float is 2.0 with limit 13 result is 0.2E1, as float is 2.0 with limit 14 result is 0.2E1, as float is 2.0 with limit 15 result is 0.2E1, as float is 2.0 with limit 16 result is 0.2E1, as float is 2.0 with limit 17 result is 0.2E1, as float is 2.0 with limit 18 result is 0.1000000000000000001E1, as float is 1.0 with limit 19 result is 0.10000000000000000007E1, as float is 1.0 with limit 20 So the results with limit <=9 or >=19 are as expected, but in between the result returned is equal to 2.0 A test that demonstrates this (suitable for inclusion in (({test/bigdecimal/test_bigdecimal.rb})) is: def test_limited_one_plus_small one = BigDecimal('1') smallnum = BigDecimal('0.7E-18') BigDecimal::save_limit do 1.upto(20) do |lim| BigDecimal::limit(lim) result = (one + smallnum).to_f.to_s assert_equal("1.0", result, "Error adding a small number to one with BigDecimal::limit(#{lim})") end end end I think this is different from #7404 (from what I can tell by google translate), but I apologize for the duplicate if not. =end -- http://bugs.ruby-lang.org/