2013-12-15 56 views
2

在Go中存儲和計算貨幣的正確方法是什麼?似乎沒有相應的十進制類型,使用浮點數是一個很大的問題。如何在Go中表示貨幣?

+1

你試過[math.big](http://golang.org/pkg/math/big/ )用你自己的定點算法在上面? – fuz

回答

5

我想說的一種方式是使用正確大小的整數類型來存儲大量的金錢,規範化爲儘可能低的金額。比方說,如果您需要以美元存儲金額降至1美分,請將您的價值乘以100,並將其存入全美分。

另一種方式是實現這將模擬什麼是「十進制」,在其他一些語言,也就是說,它會用兩個整數來表示的金額自定義類型。

+0

我喜歡這個想法。使用兩個整數(整數和十進制數)定義結構,然後可以爲您的貨幣類型聲明自定義方法,包括轉換等。 – Matt

1

理性數字是代表貨幣價值的相當好的解決方案。也就是說,這是一種具有分子和分母的類型。

通常貨幣數據結構過於複雜 - Java的BigDecimal就是一個例子。數學上更一致的方法是定義一個處理有理數的類型。當使用64位整數時,可以準確有效地表示大量的數字。錯誤和舍入問題比任何需要將二進制分數轉換爲/從小數分數的解決方案都要少。

編輯:Go標準庫包括arbitrary-precision integers and rational numbers。 Rat類型對貨幣來說效果很好,特別是那些需要任意精度的情況,例如。外匯。這裏的an example

0

這似乎是一個很好的機會,創造一個類型,它存儲在一個安全和精確的基於整數路的價值,但給你,你會從一個小數類型要額外行爲。例如,快速實現可能是這樣的(https://play.golang.org/p/nYbLiadQOc):

// USD represents US dollar amount in terms of cents 
type USD int64 

// ToUSD converts a float64 to USD 
// e.g. 1.23 to $1.23, 1.345 to $1.35 
func ToUSD(f float64) USD { 
    return USD((f * 100) + 0.5) 
} 

// Float64 converts a USD to float64 
func (m USD) Float64() float64 { 
    x := float64(m) 
    x = x/100 
    return x 
} 

// Multiply safely multiplies a USD value by a float64, rounding 
// to the nearest cent. 
func (m USD) Multiply(f float64) USD { 
    x := (float64(m) * f) + 0.5 
    return USD(x) 
} 

// String returns a formatted USD value 
func (m USD) String() string { 
    x := float64(m) 
    x = x/100 
    return fmt.Sprintf("$%.2f", x) 
} 

給定類型的行爲人們所預料的,特別是考慮到棘手的使用情況的方式。

fmt.Println("Product costs $9.09. Tax is 9.75%.") 

f := 9.09 
t := 0.0975 
ft := f * t 
fmt.Printf("Floats: %.18f * %.18f = %.18f\n", f, t, ft) 

u := ToUSD(9.09) 
ut := u.Multiply(t) 
fmt.Printf("USD: %v * %v = %v\n", u, t, ut) 

產品價格爲$ 9.09。稅率是9.75%。

花車:9.089999999999999858 * 0.097500000000000003 = 0.886275000000000035

USD:$ 9.09 * 0.0975 = $ 0.89