2011-09-18 4 views
5

Voglio convertire da cents in dollari correttamente in Ruby. Non dovrò mai lavorare con frazioni di centesimi.Converti centesimi in una stringa in dollari in Ruby senza utilizzare BigDecimal

È possibile farlo correttamente (senza errori in virgola mobile) senza dover utilizzare BigDecimal?

esempio centesimi a dollari

"99" => "0.99" 
"324" => "3.24" 

Il seguito sembra funzionare, ma è corretto?

(cents.to_i/100.0).to_s 
+0

Dipende dalla precisione necessaria. Se stai bene con precisione al centesimo, vai con la gemma dei soldi. – Philip

risposta

3

Personalmente non avrei cercato di reinventare questa ruota specifico e andare con il money gem. Dalla documentazione (enfasi aggiunta):

Caratteristiche

fornisce una classe di denaro che incapsula tutte le informazioni relative a un determinato importo di denaro, come ad esempio il suo valore e la sua moneta.

Fornisce una classe Soldi :: Valuta che incapsula tutte le informazioni su un'unità monetaria .

Rappresenta valori monetari come numeri interi, in centesimi. Questo evita errori di arrotondamento in virgola mobile.

Rappresenta la valuta Denaro :: Istanze di valute che offrono un alto livello di flessibilità.

Fornisce API per lo scambio di denaro da una valuta all'altra.

Ha la possibilità di analizzare stringhe di denaro e valuta nell'oggetto corrispondente Valuta/Valuta.

+0

In realtà money gem [utilizza BigDecimal] (https://github.com/RubyMoney/money/blob/master/lib/money/money/arithmetic.rb) per eseguire divisioni. – Philip

+0

Abbastanza giusto. Come ho detto, OP non ci ha detto troppo di quello che intende fare, ma io per primo non vorrei affrontare tutte le complessità del denaro quando qualcun altro l'ha già fatto. –

8

As Micheal Kohl already answered: Dai un'occhiata alla gemma dei soldi.

Esempio:

require 'money' 
Money.use_i18n = false #https://stackoverflow.com/q/31133229/676874 
puts Money.new(99, 'USD') 
puts Money.new(324, 'USD') 

Il seguente sembra funzionare, ma è corretto?

(cents.to_i/100.0).to_s 

Al primo sguardo, è ok, ma:

cents = '10' 
p (cents.to_i/100.0).to_s # -> '0.1' 

Non hai 2 cifre.

Alternativa:

p '%.2f' % (cents.to_i/100.0) # -> '0.10' 
+7

Grazie per aver fornito una soluzione invece di dire "usa questa gemma". –

1

È possibile considerare l'utilizzo di Razionali pure.Tuttavia, non sono sicuro ottengono convertiti galleggianti quando sprintf-ed:

"%.2f" % Rational("324".to_i,100) 
#=> "3.24" 
"%.2f" % Rational("99".to_i,100) 
#=> "0.99" 
"%.2f" % Rational("80".to_i,100) 
#=> "0.80" 
"%.2f" % Rational("12380".to_i,100) 
#=> "123.80" 
4

Se sono punge già si potrebbe usare la manipolazione di stringhe e bypassare completamente i problemi numerici:

# There are, of course, all sorts of ways to do this. 
def add_decimal(s) 
    pfx = [ '0.00', '0.0', '0.' ] 
    if(pfx[s.length]) 
     s = pfx[s.length] + s 
    else 
     s = s.dup 
     s[-2, 0] = '.' 
    end 
    s 
end 

add_decimal('')  # "0.00" 
add_decimal('1')  # "0.01" 
add_decimal('12') # "0.12" 
add_decimal('123') # "1.23" 
add_decimal('1234') # "12.34" 
add_decimal('12345') # "123.45" 

No problemi di precisione, niente virgola mobile, niente bignum, niente Rational, niente di complicato, niente di intelligente. Saranno necessarie alcune semplici modifiche per gestire i valori negativi, ma ciò sarà tanto semplice quanto ciò che è già presente.

Problemi correlati