douben6670 2017-12-25 14:11
浏览 54
已采纳

进行浮动比较[重复项]

This question already has an answer here:

In order to compare two floats (float64) for equality in Go, my superficial understanding of IEEE 754 and binary representation of floats makes me think that this is a good solution:

func Equal(a, b float64) bool {
    ba := math.Float64bits(a)
    bb := math.Float64bits(b)
    diff := ba - bb
    if diff < 0 {
        diff = -diff
    }
    // accept one bit difference
    return diff < 2
}

The question is: Is this a more generic, more precise, and more efficient, way to compare two arbitrarily large or small floats for "almost equalness", than the old abs(diff) < epsilon hack? My reasoning being that if one allows only one bit difference in the binary representation, then the compared numbers certainly could not be any more equal, apart from strict equality, which obviously (as pointed out in the comments) can be checked with == for floats.

Note: I have edited the question to make it more clear.

</div>
  • 写回答

2条回答 默认 最新

  • dongnuoyi8833 2017-12-25 16:14
    关注

    No, this is not the correct way compare floating-point values.

    You have not actually stated your real problem—there is some reason you are trying to compare two floating-point numbers, but you have not said what it is.

    Floating-point arithmetic is designed to perform approximate arithmetic. It is normal that there will be an accumulation of rounding errors in floating-point operations. These errors will generally be different when values are calculated in different ways, so floating-point arithmetic should not be expected to produce equal results.

    In your example, these operations occurred:

    • The decimal numeral “0.1” was converted to float64 (IEEE-754 64-bit binary floating-point). This produced the value 0.1000000000000000055511151231257827021181583404541015625, which is the closest float64 value to 0.1.

    • The decimal numeral “0.2” was converted to float64. This produced 0.200000000000000011102230246251565404236316680908203125, which is the closest float64 value to 0.2.

    • These were added. This produced 0.3000000000000000444089209850062616169452667236328125. In addition to the rounding errors that occurred when 0.1 and 0.2 were rounded to the nearest values in float64, this contains some additional rounding error because the exact sum cannot be represented in float64.

    • The decimal numeral “0.3” was converted to float64. This produced 0.299999999999999988897769753748434595763683319091796875, which is the closest float64 value to 0.3.

    As you can see, the result of adding 0.1 and 0.2 has accumulated different rounding errors from 0.3, so they are unequal. No correct test for equality will report they are equal. And, importantly, the errors that occurred in this example are specific to this example—different sequences of floating-point operations will have different errors, and the accumulated errors are not limited to the low bits of the numbers.

    Some people try to compare by testing whether the difference is less than some small value. This is can be okay in some applications, but is it okay in your application? We do not know what you are trying to do, so we do not know what problems will occur. Tests that allow for a small error sometimes report incorrect results, either false positives (because they accept as equal numbers that would not be equal if computed with exact mathematics) or false negatives (because they reject equality for numbers that would be equal if computed with exact mathematics). Which of these errors is worse for your application? Will one of them cause a machine to break or a person to be harmed? Without knowing that, nobody can advise which incorrect result is acceptable, or even if either is.

    Additionally, how large should the tolerance for error be? The total error that can occur in a calculation depends on the sequence of operations performed and the numbers involved. Some applications will have only a small final rounding error, and some applications can have massive errors. Nobody can give a recommendation about what value to use for the tolerance without knowing more about your specific sequence of operations. Also, the solution might not be to accept a tolerance in comparing numbers but to redesign your calculations to avoid error, or at least to reduce it.

    No general solution for comparing floating-point values for “equality” exists because it is impossible for any such solution to exist.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 救!ENVI5.6深度学习初始化模型报错怎么办?
  • ¥30 eclipse开启服务后,网页无法打开
  • ¥30 雷达辐射源信号参考模型
  • ¥15 html+css+js如何实现这样子的效果?
  • ¥15 STM32单片机自主设计
  • ¥15 如何在node.js中或者java中给wav格式的音频编码成sil格式呢
  • ¥15 不小心不正规的开发公司导致不给我们y码,
  • ¥15 我的代码无法在vc++中运行呀,错误很多
  • ¥50 求一个win系统下运行的可自动抓取arm64架构deb安装包和其依赖包的软件。
  • ¥60 fail to initialize keyboard hotkeys through kernel.0000000000