在開發(fā)的初始階段,我們經(jīng)常會(huì)遇到“浮點(diǎn)數(shù)精度”和“貨幣值表示”的問題。
那么,如何處理貨幣,如何存儲(chǔ)和傳遞它們。
Go語言中的標(biāo)準(zhǔn)浮點(diǎn)類型具有一定的精度(像其他任何語言一樣),你不能在貨幣操作中使用它們。這里有一個(gè)最簡單的例子:
var v1, v2 = 0.1, 0.2fmt.Println(v1 + v2)// 輸出:0.30000000000000004
你可以計(jì)算你需要將一個(gè)值與另一個(gè)值相加多少次,才能在你的賬戶上獲得額外的錢!但反過來也是一樣 — 在這種情況下,你只是失去了你的錢。
這不僅在對你的錢進(jìn)行數(shù)學(xué)運(yùn)算時(shí)有問題,而且在不同系統(tǒng)或服務(wù)之間傳遞數(shù)據(jù)時(shí)也是有問題的。
每次將你的錢從/到浮點(diǎn)數(shù)進(jìn)行編組時(shí),都會(huì)遇到與上述相同的問題,以及與編組器實(shí)現(xiàn)有關(guān)的其他問題 - json,xml,text等等...
另一個(gè)問題是四舍五入。如果你處理的是貨幣,你總會(huì)面臨四舍五入的問題。你應(yīng)該如何四舍五入你的貨幣值?例如 0.345 元,一般我們還是會(huì)四舍五入到 0.35 元?
有一些特殊的類型可用于貨幣的表示和計(jì)算。
Go標(biāo)準(zhǔn)庫有 big.Float 類型(來自 math/big 包,表示任意精度的浮點(diǎn)數(shù))。與 float32 和 float64 不同,它們具有固定的大小和精度,big.Float 允許你為數(shù)字和計(jì)算設(shè)置任意精度。
另一個(gè)不錯(cuò)的選擇是 decimal 庫 (https://github.com/shopspring/decimal)。
關(guān)于四舍五入:
例如,shopspring/decimal 提供了適當(dāng)舍入值的方法。
考慮的另一個(gè)好選擇是使用貨幣單位。這樣,你就從浮點(diǎn)數(shù)問題轉(zhuǎn)移到整數(shù),并將一切都作為整數(shù)計(jì)算。在這里唯一使用四舍五入的地方:傳遞結(jié)果值。
現(xiàn)在讓我們討論一下在傳遞貨幣時(shí)的選擇。
你可以在 Go Playground 上嘗試一下。
package mainimport ( "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.20.300000000000000040.3
處理貨幣時(shí) — 使用 math/big 或一些與貨幣相關(guān)的庫,比如 shopspring/decimal,或者只是使用貨幣單位,在這里不要使用浮點(diǎn)數(shù)。將貨幣作為字符串傳遞,或者在貨幣單位中傳遞,不要在這里使用浮點(diǎn)數(shù)。
本文鏈接:http://www.www897cc.com/showinfo-26-72433-0.html在Go中使用接口:實(shí)用性與脆弱性的平衡
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com