2010-01-13 6 views
8

Beim Schreiben eines Tests mit einem Wert, der als BigDecimal dargestellt wird, stieß ich auf etwas Seltsames und beschloss, mich darauf einzulassen. Kurz gesagt, wird "0,00009", wenn auf zwei Dezimalstellen gerundet, als 0,01 statt 0,00 zurückgegeben. Ja wirklich. Hier ist mein Skript/console-Capture:Ruby BigDecimal Round: Ist das ein Fehler?

>> bp = BigDecimal('0.09') 
=> #<BigDecimal:210fe08,'0.9E-1',4(8)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.09 
>> bp = BigDecimal('0.009') 
=> #<BigDecimal:210bcf4,'0.9E-2',4(8)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.01 
>> bp = BigDecimal('0.0009') 
=> #<BigDecimal:2107a8c,'0.9E-3',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.0 
>> bp = BigDecimal('0.00009') 
=> #<BigDecimal:2103428,'0.9E-4',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.01 
>> bp = BigDecimal('0.000009') 
=> #<BigDecimal:20ff0f8,'0.9E-5',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.0 

Oh, und ich bekomme die gleichen Ergebnisse, wenn ich den Standardmodus verwenden, etwa so:

>> bd = BigDecimal('0.00009') 
=> #<BigDecimal:2152ed8,'0.9E-4',4(12)> 
>> bd.round(2).to_f 
=> 0.01 

Hier sind meine Ausführungen:

ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin9.2.2] 
Rails 2.3.4 

Hat jemand so etwas gesehen?

+0

Ich kann es nicht in meiner 1.8.7 Umgebung reproduzieren (Ruby 1.8.7 (2009-06-12 Patchlevel 174) [x86_64-Linux]) – bryantsai

Antwort

6

Nein, noch nie zuvor gesehen, und es sieht definitiv wie ein Fehler aus. 0.00009 auf zwei Dezimalstellen gerundet sollte unbedingt 0.00 sein.

Die ROUND_HALF_DOWN sollte das Verhalten nicht ändern, da Sie nicht mit Mittelpunktwerten arbeiten.

This link hat weitere Details.

Es scheint sich um einen Fehler in den 1.8 Levels zu handeln, der in 1.9 behoben wurde. Es ist etwas bizarr, da es nur Zahlen mit einer geraden Anzahl von Nullen vor der ersten Ziffer ungleich Null und nur wenn diese Ziffer 5 oder größer ist.

Das scheint genau Ihr Problem basierend auf den bereitgestellten Daten.

+0

Ja, das scheint genau mein Problem zu sein! Danke für das Detektiv! –

0

Ich denke, das ist auch ein Fehler, aber was ich mich wundere, ist die .to_f, um das Ergebnis anzuzeigen. Mit BigDecimal sollten Sie .to_s ('F') stattdessen verwenden, da ich denke, dass Sie einen Grund haben, BigDecimal anstelle von Floats zu verwenden.