我发现了以下奇怪的行为。添加一些浮点会导致“随机”准确性。
所以首先我跑go version go1.12 darwin / amd64在macOS Mojave(10.14.3)上使用Intel i7 2,6 Ghz
行为 …
可能的解决方案可能是:
const float64EqThreshold = 1e-9 func equalEnought(a,b float64) bool { return math.Abs(a - b) <= float64EqThreshold }
所以功能看起来像
func TestFloatingAddition(t *testing.T) { f1 := float64(5) f2 := float64(12.1) f5 := float64(-12.1) f3 := f1 + f2 // 17.1 f4 := f3 + f5 // 5.000000000000002 if equalEnought(f1, f4){ t.Fatal("addition is not reversable") } }
这不是问题 去琅 (要么 C , C ++ , Java的 , 蟒蛇 , 红宝石 ),或任何使用的现代语言 IEEE-754 浮点表示浮点数。有些数字使用基于二进制或十进制的浮点存储格式无法准确表示。
浮点数用表示 IEEE-754 浮点为三部分,符号位,尾数和指数(使用指数偏差,偏移127,1023等,从指数中减去)。尾数被编码为二进制序列,并且基本上左/右移位指数位以形成二进制分数。二进制分数就是问题所在。
与1/3的分数相同 '相对素质' 在base-10中,并且不能用十进制精确表示,某些数字不能用二进制分数精确表示。十进制数是 '相对素质' 到二进制数,因为10 = 2 * 5有因子5.你不能将1/5精确地表示为二进制分数,就像分数1 / 3,1 / 7,1 / 11,1 / 13,1 / 17一样,等等 (注意这里的素数模式?) 不能完全表达 十进制 要么 二进制 分数。内部表示将始终接近这些数字,并且一些字符串转换库使用转换来减少近似误差。
你能做什么?如果你只使用线性算术运算符,你可以使用定点十进制库(这就是[shudder] COBOL 一样)。
有些库将分数存储为两个整数的比率,但是当您引入平方根等可能产生无理数的函数时,这并不能解决问题。