【问题标题】:Golang weird behavior when converting float to int将 float 转换为 int 时的 Golang 奇怪行为
【发布时间】:2021-04-01 16:50:25
【问题描述】:

我在 golang 中有以下代码:

var fnum float32 = 99999999;
var inum int32 = int32(fnum);
fmt.Println(inum); // This prints out 100000000

为什么 99999999 变成了 100000000? 我认为我没有超过 float32 和 int32 的限制,所以不知道为什么会发生这种情况。

【问题讨论】:

  • float32 具有 6(或 7)位有效数字的精度,这意味着任何超过该数字的内容都可能丢失。它不是 Go 特定的,实现 IEEE754 的每种语言的行为都是一样的。
  • 32 位浮点数有 24 位尾数,为您提供高达 16777216 的精确整数,您的 99999999 更大,因此会发生舍入。然而,它很奇怪,因为转换为 int 向下取整更常见......
  • @Spektre 在转换为 int 时不是“四舍五入”,而是在 var fnum float32 = 99999999; 分配期间。当int32(fnum) 发生时 - 精度已经丢失。
  • @zerkms 在将99999999 转换为float 的尾数部分时发生“转换为int”,因为尾数是24 位整数!!!所以是的,它在编译时出现在var fnum float32 = 99999999; 行中(除非你有解释环境)尾数应该保持12499999(因为这是99999999 的24 位最高有效位)但是你声称你的号码是100000000这很奇怪,但可能只是在打印过程中四舍五入尝试打印全精度,例如在. 之后打印 10 位小数,你应该会看到类似9999999?.??????????
  • @Spektre float32 不能代表 99999999100000000 是最接近的可表示值(相隔 1)。 binaryconvert.com/… Mantissa 12499999 结果到 9.9999992E7(7 分开)binaryconvert.com/result_float.html?hexadecimal=4CBEBC1F

标签: go math integer


【解决方案1】:

(IEEE 754) 32-bit float 代表表单中的真实值

value = (−1)^sign × 2^e × (1 + 2^−1 b[22] + 2^−2 b[21] + ... + 2^−23 b[0])

其中“e”是-126到+127之间的整数指数,“b[22], ..., b[0]”构成有效位。

显然,这种表示是有限的,并不是所有的实数都可以准确地表示。当涉及整数时,不能精确表示为 float32 的最小整数是 2^24 + 1 = 16777217。特别是此时的指数因子是 2^24,但最小有效数项是 2^−23 b[ 0],奇数(值%2)≠2^24以上的0不能精确表示。

同样对于值 99999999,指数因子为 2^26,2^26 以上且 (value % 8) ≠ 0 的整数无法精确表示。最接近 99999999 的可表示 float32 值是 99999992 和 100000000。

【讨论】:

    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 2017-10-16
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 2015-11-19
    • 1970-01-01
    相关资源
    最近更新 更多