IEEE 754二进制浮点数不精确 [英] IEEE 754 binary floating-point numbers imprecise for money
问题描述
当我将 math.Floor
与浮点变量一起使用时(将精度部分向下舍入/截断),我遇到了问题.我该怎么做呢?
程序包主要进口 ("fmt"数学")func main(){var st float64 = 1980var salePrice1 = st * 0.1/1.1fmt.Printf(%T:%v \ n",salePrice1,salePrice1)//179.9999var salePrice2 = math.Floor(st * 0.1/1.1)fmt.Printf(%T:%v \ n",salePrice2,salePrice2)//179}
游乐场: https://play.golang.org/p/49TjJwwEdEJ >
输出:
float64:179.99999999999997浮动64:179
我希望 1980 * 0.1/1.1
的输出为 180
,但实际输出为 179
.
原始问题:
golang的楼层号不正确
在将Math.Floor与float变量一起使用时,我遇到问题(舍入降低/截断精度部分).我该怎么做呢?
程序包主要进口 ("fmt"数学")func main(){var st float64 = 1980var salePrice1 = st * 0.1/1.1fmt.Printf(%T:%v \ n",salePrice1,salePrice1)var salePrice2 = math.Floor(st * 0.1/1.1)fmt.Printf(%T:%v \ n",salePrice2,salePrice2)}
我希望1980 * 0.1/1.1的输出为180,但实际输出是179."
游乐场:
输出:
float64:179.99999999999997浮动64:179
XY问题是在询问您尝试的解决方案,而不是实际问题: XY问题.
>很明显,这是 salePrice1
的货币计算.货币计算使用精确的十进制计算,而不是不精确的二进制浮点计算.
对于货币计算,请使用整数.例如,
程序包主要导入"fmt"func main(){var st int64 = 198000//$ 1980.00作为美分fmt.Printf(%[1] T:%[1] v \ n",st)fmt.Printf("$%d.%02d \ n",st/100,st%100)var n,d int64 = 1,11fmt.Printf(%d,%d \ n",n,d)var salePrice1 int64 =(st * n)/d//向下取整fmt.Printf(%[1] T:%[1] v \ n",salePrice1)fmt.Printf("$%d.%02d \ n",salePrice1/100,salePrice1%100)var salePrice2 int64 =((st * n)* 10/d + 5)/10//四舍五入fmt.Printf(%[1] T:%[1] v \ n",salePrice2)fmt.Printf("$%d.%02d \ n",salePrice2/100,salePrice2%100)var salePrice3 int64 =(st * n +(d-1))/d//向上舍入fmt.Printf(%[1] T:%[1] v \ n",salePrice1)fmt.Printf("$%d.%02d \ n",salePrice3/100,salePrice3%100)}
游乐场: https://play.golang.org/p/HbqVJUXXR-N
输出:
int64:198000$ 1980.001、11int64:18000$ 180.00int64:18000$ 180.00int64:18000$ 180.00
参考文献:
I have a problem when I use math.Floor
with a floating-point variable (round down/truncate the precision part). How can I do it correctly?
package main
import (
"fmt"
"math"
)
func main() {
var st float64 = 1980
var salePrice1 = st * 0.1 / 1.1
fmt.Printf("%T:%v\n", salePrice1, salePrice1) // 179.9999
var salePrice2 = math.Floor(st * 0.1 / 1.1)
fmt.Printf("%T:%v\n", salePrice2, salePrice2) // 179
}
Playground: https://play.golang.org/p/49TjJwwEdEJ
Output:
float64:179.99999999999997
float64:179
I expect the output of 1980 * 0.1 / 1.1
to be 180
, but the actual output is 179
.
The original question:
Incorrect floor number in golang
I have problem when use Math.Floor with float variable (round down/truncate the precision part). How can i do it correctly?
package main import ( "fmt" "math" ) func main() { var st float64 = 1980 var salePrice1 = st * 0.1 / 1.1 fmt.Printf("%T:%v\n", salePrice1, salePrice1) var salePrice2 = math.Floor(st * 0.1 / 1.1) fmt.Printf("%T:%v\n", salePrice2, salePrice2) }
I expect the output of 1980 * 0.1 / 1.1 to be 180, but the actual output is 179."
Playground:
Output:
float64:179.99999999999997 float64:179
The XY problem is asking about your attempted solution rather than your actual problem: The XY Problem.
Clearly, this is a money calculation for salePrice1
. Money calculations use precise decimal calculations, not imprecise binary floating-point calculations.
For money calculations use integers. For example,
package main
import "fmt"
func main() {
var st int64 = 198000 // $1980.00 as cents
fmt.Printf("%[1]T:%[1]v\n", st)
fmt.Printf("$%d.%02d\n", st/100, st%100)
var n, d int64 = 1, 11
fmt.Printf("%d, %d\n", n, d)
var salePrice1 int64 = (st * n) / d // round down
fmt.Printf("%[1]T:%[1]v\n", salePrice1)
fmt.Printf("$%d.%02d\n", salePrice1/100, salePrice1%100)
var salePrice2 int64 = ((st*n)*10/d + 5) / 10 // round half up
fmt.Printf("%[1]T:%[1]v\n", salePrice2)
fmt.Printf("$%d.%02d\n", salePrice2/100, salePrice2%100)
var salePrice3 int64 = (st*n + (d - 1)) / d // round up
fmt.Printf("%[1]T:%[1]v\n", salePrice1)
fmt.Printf("$%d.%02d\n", salePrice3/100, salePrice3%100)
}
Playground: https://play.golang.org/p/HbqVJUXXR-N
Output:
int64:198000
$1980.00
1, 11
int64:18000
$180.00
int64:18000
$180.00
int64:18000
$180.00
References:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
How should we calc money (decimal, big.Float)
这篇关于IEEE 754二进制浮点数不精确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!