Bugs: Browse | Submit New | Admin

[#14271] BigDecimal("0.00005").round == 1

Date:
2007-09-27 11:21
Priority:
3
Submitted By:
Jano Svitok (janek)
Assigned To:
Akinori MUSHA (knu)
Category:
Math
State:
Open
Platform:
 
Summary:
BigDecimal("0.00005").round == 1

Detailed description
from ruby-talk:271159

A coworker discovered some disturbing behavior in BigDecimal#round.
The output I get from the program below is:

===== begin output

These values appended to '0.0000' cause BigDecimal#round to return
nonzero:
[5, 6, 7, 8, 9, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99]

These numbers of zeroes between the decimal point and a 7 cause
BigDecimal#round to return nonzero:
[4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72,
76, 80, 84, 88, 92, 96, 100]

===== end output

===== begin code

require 'bigdecimal'

vary_number_after_four_zeroes = (1..100).map { |i|
 bd = BigDecimal.new("0.0000#{i}"); [i, bd.round.to_s]
}
seed_values_triggering_misbehavior_with_four_zeroes =
 vary_number_after_four_zeroes.reject {|i, bds| bds == '0.0'}.map {|
i, bds| i}

vary_number_of_zeroes = (1..100).map { |i|
 bd = BigDecimal.new("0.#{'0' * i}7"); [i, bd.round.to_s]
}
number_of_zeroes_triggering_misbehavior =
 vary_number_of_zeroes.reject {|i, bds| bds == '0.0'}.map {|i, bds|
i}

puts "These values appended to '0.0000' cause BigDecimal#round to
return nonzero:"
p seed_values_triggering_misbehavior_with_four_zeroes
puts
puts "These numbers of zeroes between the decimal point and a 7 cause
BigDecimal#round to return nonzero:"
p number_of_zeroes_triggering_misbehavior

===== end code

I get identical reports on Linux and Windows versions of Ruby:

ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-linux]

ruby 1.8.6 (2007-03-13 patchlevel 0) [i386-mswin32]

We would be grateful for a pointer to a patch that fixes this issue if
one is available.

------------------------------

The problem is most probably in ext/bigdecimal/bigdecimal.c, VpMidRound().

It happens when 1. the number of leading
zeros is divisible by 4 (BASE_FIG, the number of decimal digits stored
in one U_LONG), and the next digit is >= 5 (I guess due to selected
rounding mode)

That means, the problematic numbers have format 0.XE-Y where X in
[5..9] and Y%4 == 0

It's even visible in
BigDecimal.new("0.5").round(-4).to_i # => 10000
BigDecimal.new("0.000000005").round(4) #=> 0.1E-3 == 0.0001
BigDecimal.new("0.000000005").round(-4) #=> 0.1E5 == 10000

Add A Comment: Notepad

Please login


Followup

Message
Date: 2008-11-15 19:42
Sender: Roger Pack

may want to check that the patch worked:
http://redmine.ruby-lang.org/issues/show/740
Thanks!
Date: 2008-11-11 01:28
Sender: Roger Pack

created http://redmine.ruby-lang.org/issues/show/740
Date: 2008-11-08 01:08
Sender: Roger Pack

appears to work on 1.9, broken on 1.8
Could you submit a new copy to the new tracker:
http://redmine.ruby-lang.org/
--this tracker is being shelved.
Thanks!
-=R
Date: 2008-03-05 22:17
Sender: Jano Svitok

Patch for this issue is in
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/27336
0

I guess it was discussed in
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/32659
-- I don't understand Japanese :(
Date: 2007-09-30 19:53
Sender: Jano Svitok

some BigDecimal tests can be found at
http://svn.codehaus.org/jruby/trunk/jruby/test/test_big_decimal.r
b

Attached Files:

Name Description Download
No Files Currently Attached

Changes:

Field Old Value Date By
summaryBigDecimal("0.00005").round == 12008-03-05 22:17janek
summaryBigDecimal("0.00005").round == 12007-09-30 19:53janek