亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go - 貨幣計算

Go - 貨幣計算

冉冉說 2021-11-29 19:29:00
我正在嘗試用 Go 進行貨幣計算。環顧標準庫,big/math似乎是我可以利用的。我運行了一些代碼來檢查它是如何工作的。首先我用 Float.SetFloat64()var f = 18.9var f2 = 1.65bf := new(big.Float)bf.Add(bf, new(big.Float).SetFloat64(f))bf.Add(bf, new(big.Float).SetFloat64(f2))result, _ := bf.Float64()fmt.Println(result)這給了我結果:20.549999999999997就像用float64類型計算一樣。既然我在和錢打交道,結果一定是20.55。相反,當使用 Float.SetString()var s = fmt.Sprintf("%f", 18.9)var s2 = fmt.Sprintf("%f", 1.65)bf := new(big.Float)bf2, _ := new(big.Float).SetString(s)bf3, _ := new(big.Float).SetString(s2)bf.Add(bf, bf2)bf.Add(bf, bf3)result, _ := bf.Float64()fmt.Println(result)這給了我結果:20.55似乎我可以將它用于我的目的(但我不確定..)。我的問題是為什么使用Float.SetFloat64()和 之間有區別Float.SetString()?Float.SetString()用于貨幣計算時是否有任何陷阱?提前致謝,請原諒我的英語。[編輯]我知道應該避免使用浮點類型來表示貨幣價值。但類型的選擇并不在我的控制之下..我想知道以上兩個問題中的一個(或兩個)的答案。或者為什么Float.SetString()給我看似正確的結果的原因也很有幫助。
查看完整描述

3 回答

?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

永遠,永遠,永遠不要使用浮動貨幣。它是一種不精確的類型,因此您最終不得不四舍五入計算并且最終在這里和那里損失(或獲得)一分錢。您可能認為這沒問題,但您的會計師會告訴您不是。你必須完全準確。

因此,要么使用專門的任意精度十進制類型,要么使用整數并保存一分錢(或一分錢的分數)并適當地顯示它。(就像您如何將日期保存為自 1970 年以來的秒數,但將它們顯示為 dd-mm-yyyy)。

附注。切勿使用浮動貨幣。真的。

聚苯乙烯。不要使用浮動貨幣,永遠不要永遠。


查看完整回答
反對 回復 2021-11-29
?
肥皂起泡泡

TA貢獻1829條經驗 獲得超6個贊

使用big.Int代表 1000ths 或 10000ths 一分的值。浮點值不適用于貨幣,尤其是在交易時。如果有人要求您使用浮點值,請嘗試說服他們這是一個壞主意。如果那不起作用,請重新考慮您與他們合作的決定??紤]到您可能會無意中卷入非法活動:https : //en.wikipedia.org/wiki/Salami_slicing

回答您的技術問題:

big.Float值不是像big.Int值那樣的任意精度。

SetFloat64將浮點數的精度設置為一段float64時間的精度,SetString根據字符串的內容進行設置。

無論哪種方式,您都希望對 big.Float 值設置的精度進行深思熟慮。您可以使用https://golang.org/pkg/math/big/#Float.SetPrec控制它SetPrec

編輯:

至于陷阱,請考慮基數 10 中的 0.10 在基數 2 中沒有有限表示。由于big.Float沒有base字段或與之對應的任何內容,因此它實際上無法準確存儲 0.10。

基本上,只要您使用 Float 作為浮點數而不是整數,您就會留下確切的值。


查看完整回答
反對 回復 2021-11-29
?
暮色呼如

TA貢獻1853條經驗 獲得超9個贊

您可以使用實現“無限精度”十進制算術的gopkg.in/inf.v0。


對于上面指定的金額,這里是一個例子:


func main() {

    var amt inf.Dec

    amt.SetUnscaled(1890)

    amt.SetScale(2)

    fmt.Println(amt.String())

    var amt1 inf.Dec

    amt1.SetUnscaled(165)

    amt1.SetScale(2)

    fmt.Println(amt1.String())

    var total = inf.NewDec(5, 2)

    total = total.Add(&amt, &amt1)

    fmt.Println(total.String())

}

它應該按預期打印出 20.55。


查看完整回答
反對 回復 2021-11-29
  • 3 回答
  • 0 關注
  • 366 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號