为什么Go和Python在分割大数字时会返回不同的结果?

use*_*730 -5 python numbers division go

// In golang    
x, y := big.NewFloat(26959535291011309493156476344723991336010898738574164086137773096960), big.NewFloat(14484.162361)  
z := new(big.Float).Quo(x, y)
fmt.Println(fmt.Sprintf("%f", z))
Run Code Online (Sandbox Code Playgroud)

输出:1861311315012765262390495455137379355146730679910059382988079104.000000

// In python
v1 = 26959535291011309493156476344723991336010898738574164086137773096960000000
v2= 14484162361
print v1/v2
Run Code Online (Sandbox Code Playgroud)

输出:1861311315012765306929610463010191006516769515973403833769533170

icz*_*cza 6

你没有在Go和Python中做同样的操作.在Go中,您可以划分2个浮点数,而在Python中则可以划分2个整数.结果只是"大致"相等,因为您提供的输入数字会丢失精度,浮点运算的准确性也会受到限制(不足).

如果在Go中执行相同的整数除法(使用big.Int类型),则会得到相同的结果:

i, ok := big.NewInt(0).SetString("26959535291011309493156476344723991336010898738574164086137773096960000000", 10)
if !ok {
    panic("invalid")
}
j, ok := big.NewInt(0).SetString("14484162361", 10)
if !ok {
    panic("invalid")
}

k := big.NewInt(0).Quo(i, j)
fmt.Println(k)
Run Code Online (Sandbox Code Playgroud)

这输出:

1861311315012765306929610463010191006516769515973403833769533170
Run Code Online (Sandbox Code Playgroud)

如果要在Go中执行浮点除法,请不要使用float64类型来表示输入,因为它们的精度有限.这将发生,因为您创建了big.NewFloat()具有float64类型参数的输入数字,因此您传递的常量将被隐式转换为float64您已经失去精度.

而是使用big.Float类型,并将输入指定为string值并使用它进行设置Float.SetString(); 并手动增加精度(使用Float.SetPrec()).如果这样做,您将得到"相同"的结果(整数部分相同,加上一些分数值):

x, ok := big.NewFloat(0).SetPrec(500).SetString("26959535291011309493156476344723991336010898738574164086137773096960")
if !ok {
    panic("invalid")
}
y, ok := big.NewFloat(0).SetPrec(500).SetString("14484.162361")
if !ok {
    panic("invalid")
}
z := new(big.Float).SetPrec(500).Quo(x, y)
fmt.Println(fmt.Sprintf("%f", z))
Run Code Online (Sandbox Code Playgroud)

输出:

1861311315012765306929610463010191006516769515973403833769533170.518151
Run Code Online (Sandbox Code Playgroud)

试试Go Playground上的例子.

请注意,精度Float.Quo()取决于:

精确度,舍入度和准确度报告与Add相同.

这是:

如果z的精度为0,则在操作之前将其更改为x或y的精度中的较大者.根据z的精度和舍入模式执行舍入; 和z的准确度报告相对于精确(非舍入)结果的结果错误.