https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112013-12-30T00:42:12ZRuby Issue Tracking SystemBackport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439402013-12-30T00:42:12Zdmarkow (Dylan Markow)dmarkow@gmail.com
<ul></ul><p>=begin<br>
The to_f appears to be irrelevant:</p>
<p>2.0.0p353:</p>
<blockquote>
<blockquote>
<p>BigDecimal.new("1472.0") / BigDecimal.new("0.99")<br>
=> 1486.868686869</p>
</blockquote>
</blockquote>
<p>2.1.0:</p>
<blockquote>
<blockquote>
<p>BigDecimal.new("1472.0") / BigDecimal.new("0.99")<br>
=> 1487.0<br>
=end</p>
</blockquote>
</blockquote> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439412013-12-30T00:46:24Zdmarkow (Dylan Markow)dmarkow@gmail.com
<ul></ul><p>=begin<br>
Also, it appears to only happen when the right side number is less than 1:</p>
<blockquote>
<blockquote>
<p>BigDecimal.new("1472.0") / BigDecimal.new("0.99")<br>
1487.0 # Should be 1486.868686869<br>
BigDecimal.new("1472.0") / BigDecimal.new("1.0")<br>
1472.0 # Correct<br>
BigDecimal.new("1472.0") / BigDecimal.new("1.01")<br>
1457.425742574257425743 # Correct<br>
=end</p>
</blockquote>
</blockquote> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439482013-12-30T03:30:53Zzzak (zzak _)
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>mrkn (Kenta Murata)</i></li><li><strong>Target version</strong> set to <i>2.2.0</i></li></ul><p>Thanks for the report, I'll leave this one to murata-san since he knows the spec</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439522013-12-30T08:06:47Zal2o3cr (Matt Jones)al2o3cr@gmail.com
<ul></ul><p>Still fuzzy on the cause, but the behavior is interesting - it appears that something has changed regarding the way that non-terminating decimals are rounded.</p>
<p>There's also some magnitude-dependent behavior: 147.2 / 0.099 (and related variants shifting the decimals around) don't always return the same value.</p>
<p>Here's a little program to compare the behavior for different offsets:</p>
<p><a href="https://gist.github.com/al2o3cr/8175722" class="external">https://gist.github.com/al2o3cr/8175722</a></p>
<p>Attached to that are also the results of running the script on 2.0.0 and 2.1.0.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439532013-12-30T09:19:13Zal2o3cr (Matt Jones)al2o3cr@gmail.com
<ul></ul><p>Updated - I added a dump of the Prec + MaxPrec values to the output of the script. There definitely appears to be a pattern, where inputs with the same precision values produce the same results.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439612013-12-30T16:28:32Zphasis68 (Heesob Park)phasis@gmail.com
<ul></ul><p>It seems that the size of exponenent affects the precison of division result, but that is a wrong assumption.<br>
I think the mininum precison is required regardless of the size of exponent.</p>
<p>irb(main):001:0> puts BigDecimal.new('1') / BigDecimal.new('3')<br>
0.333333333E0<br>
irb(main):002:0> puts BigDecimal.new('0.1') / BigDecimal.new('0.3')<br>
0.0<br>
irb(main):003:0> puts BigDecimal.new('0.01') / BigDecimal.new('0.03')<br>
0.0<br>
irb(main):004:0> puts BigDecimal.new('0.001') / BigDecimal.new('0.003')<br>
0.0<br>
irb(main):005:0> puts BigDecimal.new('0.00000000001') / BigDecimal.new('0.00000000003')<br>
0.333333333E0</p>
<p>Here is a simple patch to ensure the minimun precison of division result.</p>
<p>diff --git a/bigdecimal.c b/bigdecimal.c.new<br>
index e0b7c01..615c15f 100644<br>
--- a/bigdecimal.c<br>
+++ b/bigdecimal.c.new<br>
@@ -1222,6 +1222,7 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)<br>
*div = b;<br>
mx = a->Prec + vabs(a->exponent);<br>
if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);</p>
<ul>
<li>
<p>if (mx<3) mx = 3;<br>
mx =(mx + 1) * VpBaseFig();<br>
GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));<br>
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));<br>
@@ -1323,6 +1324,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)</p>
<p>mx = a->Prec + vabs(a->exponent);<br>
if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);</p>
</li>
<li>
<p>if (mx<3) mx = 3;<br>
mx = (mx + 1) * VpBaseFig();<br>
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));<br>
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));</p>
</li>
</ul>
<p>After appling the patch, the results are all equal.</p>
<p>irb(main):001:0> puts BigDecimal.new('1') / BigDecimal.new('3')<br>
0.333333333333333333E0<br>
irb(main):002:0> puts BigDecimal.new('0.1') / BigDecimal.new('0.3')<br>
0.333333333333333333E0<br>
irb(main):003:0> puts BigDecimal.new('0.01') / BigDecimal.new('0.03')<br>
0.333333333333333333E0<br>
irb(main):004:0> puts BigDecimal.new('0.001') / BigDecimal.new('0.003')<br>
0.333333333333333333E0<br>
irb(main):005:0> puts BigDecimal.new('0.00000000001') / BigDecimal.new('0.00000000003')<br>
0.333333333333333333E0</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=439752013-12-31T01:47:56Zehutzelman (Eric Hutzelman)ehutzelman@gmail.com
<ul></ul><p>=begin<br>
I'm also seeing some different rounding/conversion in 2.1.0p0 when using BigDecimal and Floats:</p>
<p>((<em>Ruby 2.0.0p353:</em>))</p>
<blockquote>
<blockquote>
<p>0.25 / BigDecimal.new("0.5")<br>
=> 0.5<br>
_.class<br>
=> Float</p>
</blockquote>
</blockquote>
<p>((<em>Ruby 2.1.0p0:</em>))</p>
<blockquote>
<blockquote>
<p>0.25 / BigDecimal.new("0.5")<br>
=> 0.0<br>
_.class<br>
=> BigDecimal</p>
</blockquote>
</blockquote>
<p>=end</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=440262014-01-03T05:52:18Zal2o3cr (Matt Jones)al2o3cr@gmail.com
<ul></ul><p>phasis68 (Heesob Park) wrote:</p>
<blockquote>
<p>Here is a simple patch to ensure the minimun precison of division result.</p>
<p>diff --git a/bigdecimal.c b/bigdecimal.c.new<br>
index e0b7c01..615c15f 100644<br>
--- a/bigdecimal.c<br>
+++ b/bigdecimal.c.new<br>
@@ -1222,6 +1222,7 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)<br>
*div = b;<br>
mx = a->Prec + vabs(a->exponent);<br>
if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);</p>
<ul>
<li>
<p>if (mx<3) mx = 3;<br>
mx =(mx + 1) * VpBaseFig();<br>
GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));<br>
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));<br>
@@ -1323,6 +1324,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)</p>
<p>mx = a->Prec + vabs(a->exponent);<br>
if (mxPrec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);</p>
</li>
<li>
<p>if (mx<3) mx = 3;<br>
mx = (mx + 1) * VpBaseFig();<br>
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));<br>
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));</p>
</li>
</ul>
</blockquote>
<p>Not a fan of this, since it's updating code that didn't change between the two releases (as far as I can tell). I'd prefer to fix the underlying reason why identical calculations in 2.0 and 2.1 aren't behaving the same way instead of just arbitrarily forcing more precision...</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=440402014-01-03T10:52:52Zariveira (Alexandre Riveira)alexandre@objectdata.com.br
<ul></ul><p>When upgrading to ruby 2.1 calculate a percentage in our system broke<br>
example</p>
<p>v1 = BigDecimal.new("0.94")<br>
v2 = BigDecimal.new("0.97")<br>
puts (((v2 - v1) * 100) / v1).to_f</p>
<p>ruby 2.0 => 3.191489362<br>
ruby 2.1 => 3.0</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=441612014-01-08T08:28:31Zkwerle (Kurt Werle)kurt@CircleW.org
<ul></ul><p>This looks like the same thing as <a href="https://bugs.ruby-lang.org/issues/9305" class="external">https://bugs.ruby-lang.org/issues/9305</a></p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=441972014-01-10T03:40:31Zkwerle (Kurt Werle)kurt@CircleW.org
<ul></ul><p>It is worth noting that replacing the ruby 2.1 implementation of BigDecimal with the 2.0 implementation works and makes this issue go away. The downside is that there are a few BigDecimal tests that fail. At a glance, they all look like new BigDecimal functionality.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=442662014-01-13T17:03:27Zmrkn (Kenta Murata)muraken@gmail.com
<ul></ul><p>This behavior change had been introduced from the version 1.2.2, which was released on 2013-11-22.</p>
<p>This change can be thought as a bug fix for the former behavior which calculates too many digits. I thought so when I implemented it.<br>
For example, BigDecimal("1472.0") is 5-digit floating-point number and BigDecimal("0.99") is 2-digit floating-point number, so the result of BigDecimal("1472.0") / BigDecimal("0.99") has three exact digits and one ambiguous digit.</p>
<p>The reason why I implemented this behavior is that the "/" operator cannot determine the precision of the quotient generally because it cannot obtain the 2nd parameter to get the precision.</p>
<p>However, since the current precision system isn't strictly implemented, I think the current behavior is too strict for practical use.<br>
For instance, BigDecimal("0.1200") cannot represent a 4-digit floating-point number in the current implementation.</p>
<p>So I'll fix it soon, but I'll put it back after I make the precision system more strict.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=442672014-01-13T17:37:00Zmrkn (Kenta Murata)muraken@gmail.com
<ul></ul><p>I've fixed this and released the new bigdecimal version 1.2.4.</p>
<p>Please do <code>gem install bigdecimal</code> and check it as the following:</p>
<pre><code>gem 'bigdecimal', '>= 1.2.4'
require 'bigdecimal'
puts BigDecimal('1472.0') / BigDecimal('0.99')
</code></pre> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=442682014-01-13T17:39:06Zmrkn (Kenta Murata)muraken@gmail.com
<ul><li><strong>Tracker</strong> changed from <i>Bug</i> to <i>Backport</i></li><li><strong>Project</strong> changed from <i>Ruby master</i> to <i>Backport21</i></li><li><strong>Category</strong> deleted (<del><i>lib</i></del>)</li><li><strong>Assignee</strong> changed from <i>mrkn (Kenta Murata)</i> to <i>naruse (Yui NARUSE)</i></li><li><strong>Target version</strong> deleted (<del><i>2.2.0</i></del>)</li></ul><p>I think it needs to be backported to 2.1 and 2.0.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=443482014-01-15T15:21:21Zmrkn (Kenta Murata)muraken@gmail.com
<ul></ul><p>bigdecimal 1.2.4 failed to support Ruby 1.9.3.<br>
Please use the version 1.2.5 for Ruby 1.9.3.</p> Backport21 - Backport #9316: BigDecimal division in Ruby 2.1https://bugs.ruby-lang.org/issues/9316?journal_id=446312014-01-27T07:57:20Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>Applied in changeset r44711.</p>
<hr>
<p>merge revision(s) 44588: [Backport <a class="issue tracker-4 status-5 priority-4 priority-default closed" title="Backport: BigDecimal division in Ruby 2.1 (Closed)" href="https://bugs.ruby-lang.org/issues/9316">#9316</a>]</p>
<pre><code>* ext/bigdecimal/bigdecimal.c (BigDecimal_divide): Add an additional
digit for the quotient to be compatible with bigdecimal 1.2.1 and
the former. <a href="/issues/9316">[ruby-core:59365]</a> [#9316] [#9305]
* test/bigdecimal/test_bigdecimal.rb: tests for the above change.
* ext/bigdecimal/bigdecimal.gemspec: bigdecimal version 1.2.4.
</code></pre>