go貨幣計算時如何避免浮點數(shù)精度問題
在開發(fā)的初始階段,我們經(jīng)常會遇到“浮點數(shù)精度”和“貨幣值表示”的問題。
那么,如何處理貨幣,如何存儲和傳遞它們。
為什么是問題
Go語言中的標(biāo)準(zhǔn)浮點類型具有一定的精度(像其他任何語言一樣),你不能在貨幣操作中使用它們。這里有一個最簡單的例子:
var v1, v2 = 0.1, 0.2 fmt.Println(v1 + v2) // 輸出:0.30000000000000004
你可以計算你需要將一個值與另一個值相加多少次,才能在你的賬戶上獲得額外的錢!但反過來也是一樣 — 在這種情況下,你只是失去了你的錢。
這不僅在對你的錢進(jìn)行數(shù)學(xué)運(yùn)算時有問題,而且在不同系統(tǒng)或服務(wù)之間傳遞數(shù)據(jù)時也是有問題的。
下一個問題 — 傳遞你的錢
每次將你的錢從/到浮點數(shù)進(jìn)行編組時,都會遇到與上述相同的問題,以及與編組器實現(xiàn)有關(guān)的其他問題 - json,xml,text等等...
另一個問題是四舍五入。如果你處理的是貨幣,你總會面臨四舍五入的問題。你應(yīng)該如何四舍五入你的貨幣值?例如 0.345 元,一般我們還是會四舍五入到 0.35 元?
我們的選擇是什么
有一些特殊的類型可用于貨幣的表示和計算。
Go標(biāo)準(zhǔn)庫有 big.Float
類型(來自 math/big
包,表示任意精度的浮點數(shù))。與 float32
和 float64
不同,它們具有固定的大小和精度,big.Float
允許你為數(shù)字和計算設(shè)置任意精度。
另一個不錯的選擇是 decimal
庫 github.com/shopspring/decimal
關(guān)于四舍五入:
- 1.234 => 1.23
- 1.235 => 1.24
- 1.236 => 1.24
例如,shopspring/decimal
提供了適當(dāng)舍入值的方法。
考慮的另一個好選擇是使用貨幣單位。這樣,你就從浮點數(shù)問題轉(zhuǎn)移到整數(shù),并將一切都作為整數(shù)計算。在這里唯一使用四舍五入的地方:傳遞結(jié)果值。
現(xiàn)在讓我們討論一下在傳遞貨幣時的選擇。
- 使用貨幣單位 — 我們將所有內(nèi)容都傳遞為整數(shù),這里沒有浮點問題。只需控制值的限制,就可以了。
- 將浮點數(shù)作為字符串傳遞。通常也是一個不錯的選擇 — 當(dāng)你將浮點數(shù)作為字符串傳遞時,帶有所需精度(特定小數(shù)位數(shù))的字符串,當(dāng)對方讀取此字符串值并將其轉(zhuǎn)換回浮點數(shù)時,你就是安全的。
簡單的例子
你可以在 Go Playground 上嘗試一下。
package main import ( "fmt" "github.com/shopspring/decimal" ) func main() { a := 0.1 b := 0.2 c := decimal.NewFromFloat(a) d := decimal.NewFromFloat(b) fmt.Println(a, b, c.String(), d.String()) fmt.Println(a + b) fmt.Println(c.Add(d).String()) }
輸出為:
0.1 0.2 0.1 0.2
0.30000000000000004
0.3
結(jié)論
處理貨幣時 — 使用 math/big
或一些與貨幣相關(guān)的庫,比如 shopspring/decimal
,或者只是使用貨幣單位,在這里不要使用浮點數(shù)。將貨幣作為字符串傳遞,或者在貨幣單位中傳遞,不要在這里使用浮點數(shù)。
其實還有一個小技巧:對于這些數(shù)值,我們可以使用:xxx * 10000
的方式,這樣我們就可以保留其精度。10000
這個值可以在團(tuán)隊內(nèi)協(xié)商。
到此這篇關(guān)于go貨幣計算時如何避免浮點數(shù)精度問題的文章就介紹到這了,更多相關(guān)go浮點數(shù)精度問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP
這篇文章主要為大家介紹了Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Golang算法問題之整數(shù)拆分實現(xiàn)方法分析
這篇文章主要介紹了Golang算法問題之整數(shù)拆分實現(xiàn)方法,結(jié)合實例形式分析了Go語言數(shù)值運(yùn)算與數(shù)組遍歷相關(guān)操作技巧,需要的朋友可以參考下2017-02-02