2010-01-13 10 views
8

Durante la scrittura di un test con un valore che viene rappresentato come un BigDecimal, mi sono imbattuto in qualcosa di strano ed ha deciso di scavare in esso. In breve, '0,00009' se arrotondato a due cifre decimali viene restituito come 0,01 anziché 0,00. Veramente. Ecco la mia cattura script/console:Ruby BigDecimal Round: si tratta di un errore?

>> 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, e ottenere gli stessi risultati se uso la modalità di default, in questo modo:

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

Qui sono le mie versioni:

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

Qualcuno ha mai visto qualcosa del genere?

+0

Non riesco a riprodurlo nel mio ambiente 1.8.7 (ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]) – bryantsai

risposta

6

No, mai visto prima, e sembra decisamente come un insetto. 0.00009 arrotondato a due cifre decimali deve essere sicuramente 0.00.

Il ROUND_HALF_DOWN non dovrebbe modificare il comportamento dal momento che non ha a che fare con i valori del punto medio.

This link ha più dettagli.

sembra essere un bug nei livelli 1.8 che è stato risolto in 1.9. È un po 'bizzarro in quanto sembra influenzare solo i numeri con un numero pari di zeri prima della prima cifra diversa da zero e solo se quella cifra è 5 o maggiore.

Questo sembra essere esattamente il il problema in base ai dati forniti.

+0

Sì, questo sembra essere esattamente il mio problema! Grazie per l'investigazione! –

0

Penso che anche questo sia un errore, ma quello che mi chiedo è il .to_f per visualizzare il risultato. Con BigDecimal dovresti usare .to_s ('F') invece dal momento che immagino tu abbia un motivo per usare BigDecimal invece di Floats.