为什么这两个大浮点值不相等?

在过去的2周里,我一直在研究浮点的行为和功能,特别是GO中的大浮点。我遇到了许多行为,并自己找到了答案。但是,仍然有一个答案我找不到自己。


https://play.golang.org/p/-y0oeb2Jisv


value1 := big.NewFloat(137216723432.8234782347)

value2 := big.NewFloat(71371.92602458)

for i := 0; i < 300; i++ {

    value1.Sub(value1, value2)

}


value3 := big.NewFloat(137216723432.8234782347)

value4 := big.NewFloat(71371.92602458)

for i := 0; i < 300; i++ {

    result := big.NewFloat(0).Sub(value3,value4)

    value3.Set(result)

}


encodedValue1, _ := value1.GobEncode()

encodedValue3, _ := value3.GobEncode()


if value1 == value3 {

    fmt.Println("values are equal" , value1 , value3)

} else {

    fmt.Println("values are not equal", value1 ,value3)

}


fmt.Println("difference is here:\n", encodedValue1,"\n", encodedValue3)

为什么这两个操作的结果不相等?根据我的理解,这与精度/准确性/舍入模式有关。


蓝山帝景
浏览 63回答 1
1回答

偶然的你

value1和 是指针,因此比较这些指针,而不是指向的值。可能有 2 个指向的对象相等,但它们的地址不相等。value3value1 == value3比较大。浮点值(或 ),请使用浮点值。如果 2 个值(它们表示的数字)相等,则返回。*big.Float0if value1.Cmp(value3) == 0 {&nbsp; &nbsp; fmt.Println("values are equal", value1, value3)} else {&nbsp; &nbsp; fmt.Println("values are not equal", value1, value3)}有了这个变化,输出将是(在Go Playground上尝试):values are equal 1.3719531185501585e+11 1.3719531185501585e+11difference is here:&nbsp;[1 2 0 0 0 53 0 0 0 37 255 139 210 151 120 32 120 0]&nbsp;&nbsp;[1 10 0 0 0 53 0 0 0 37 255 139 210 151 120 32 120 0]因此,表示的数字是相等的。Float.GobEncode()&nbsp;返回的序列化二进制形式是不一样的,但这并不意味着表示的数字不相等。正如其文档所述:戈布代码实现了这个贪婪。Gob编码器接口。将封送处理 Float 值及其所有属性(精度、舍入模式、准确性)。输出是不同的,因为 的内部结构不相同(在本例中为精度)。在这种情况下,即使您可以比较指向的对象,这些对象也不会相同,但表示的数字是相同的。同样,始终使用提供的方法比较复杂对象,当然不是地址。big.Float此示例中的差异来自存储的精度字段:fmt.Println(value1.Acc()) fmt.Println(value3.Acc())哪些输出(在Go游乐场上尝试):Below Exact返回的精度是“最近操作产生的x的精度”。由于在 和 上执行的最后一个操作不相同( 和 ),因此精度字段不一定相同(并且在此示例中它们确实不同)。由于准确性属性也包含在 Gob 序列化表单中,因此它们的序列化表单不同。Float.Acc()value1value3value1.Sub()value3.Set()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go