当前位置: 首页 > 面试题库 >

进行浮动比较

葛炜
2023-03-14
问题内容

为了比较两个浮点数(float64)在Go中的相等性,我对IEEE 754和浮点数的二进制表示的肤浅理解使我认为这是一个很好的解决方案:

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
}

问题是:与旧的abs(diff) < epsilonhack 相比,这是一种更通用,更精确,更有效的方法来比较两个任意大或小的浮点数以“几乎相等”
吗?我的理由是,如果一个二进制表示形式仅允许一位差异,那么除了严格的相等性(显然可以如注释中所指出的那样)之外,比较的数字当然不能再相等了(可以在注释中指出)==

注意:我已经编辑了问题以使其更清楚。


问题答案:

不,这不是比较浮点值的正确方法

您实际上并没有说出真正的问题-出于某些原因要尝试比较两个浮点数,但是您没有说出它是什么。

浮点算术旨在执行近似算术。通常在浮点运算中会产生舍入误差。当以不同方式计算值时,这些误差通常会有所不同,因此不应期望浮点算术产生相同的结果。

在您的示例中,发生了以下操作:

  • 十进制数字“ 0.1”被转换为float64(IEEE-754 64位二进制浮点数)。这产生了值0.1000000000000000055511151231257827021181583404541015625,它是最接近float640.1的值。

  • 十进制数字“ 0.2”被转换为float64。这产生了0.200000000000000011102230246251565404236316680908203125,它是最接近float640.2的值。

  • 这些已添加。这产生了0.3000000000000000444089209850062616169452667236328125。除了将0.1和0.2舍入到in中的最接近值时发生的舍入误差外float64,这还包含一些额外的舍入误差,因为无法在中表示精确的和float64

  • 十进制数字“ 0.3”转换为float64。这产生了0.299999999999999988897769753748434595763683319091796875,它是最接近float640.3的值。

如您所见,相加0.1和的结果与0.2累计了不同的舍入误差0.3,因此它们是不相等的。没有正确的平等测试会报告他们平等。而且,重要的是,此示例中发生的错误是此示例特有的-
不同的浮点运算序列将具有不同的错误,并且累积的错误 不限于数字的低位

有人尝试通过测试差异是否小于某个小值来进行比较。在某些应用程序中可以这样做,但是在您的应用程序中可以吗?我们不知道您要做什么,因此我们不知道会发生什么问题。允许出现小错误的测试有时会报告错误的结果,要么是误报(因为接受的是相等的数字,如果使用精确的数学计算将不会等于结果),要么是误报负的(因为接受测试的结果是相等的数字,如果使用精确的数学计算将不会相等)精确数学)。这些错误中的哪一个对您的应用最严重?其中之一会导致机器损坏或对人造成伤害吗?在不知道这一点的情况下,没有人会建议哪个错误的结果是可以接受的,甚至可以接受。

此外,误差的容忍度应该是多大?计算中可能发生的总误差取决于执行的操作顺序和涉及的数量。有些应用程序的最终取整误差很小,而有些应用程序的误差很大。在不进一步了解您的特定操作顺序的情况下,没有人会建议使用什么值作为公差。同样,解决方案可能不是在比较数字时接受公差,而是重新设计计算以避免错误或至少减少误差。

不存在用于比较浮点值是否相等的通用解决方案,因为不可能存在任何这样的解决方案。



 类似资料:
  • 问题内容: 我刚刚阅读了有关浮点值比较的声明 不得使用==或!=运算符比较浮点值。大多数浮点值没有精确的二进制表示形式,并且精度有限。 如果是这样,比较两个浮点值的最佳方法是什么? 问题答案: 以下扩展方法对于实现Kevin的建议可能有用: 现在,您可以执行以下操作: 只需将更改为更合适的名称,或在需要时将默认边距更改为比更好的值。

  • 问题内容: 我只在div中遇到浮动元素问题,这是问题所在: 我需要有关第二个DIV的边框及其内容位置的说明。为什么边框在后面但内容在第一格之下? 还根据:https : //css-tricks.com/all-about-floats/#article-header-id-3 关于浮点数的更令人困惑的事情之一是它们如何影响包含它们的元素(它们的“父”元素)。如果此父元素只包含浮点元素,则其高度实

  • 对于这些代码行,我得到0作为输出,即它们都是相等的。现在,如果我理解正确,a b和c可能会存储稍微不同版本的真值.3因此,当做一个Float.compare(...)对这些值,我希望得到一个输出值,而不是0。为什么我把它们取为0?

  • 问题内容: 我已经在SO上看到了几次这样的问题,并且给出了相同的答案,但这些答案在我的Chrome或Firefox中不起作用。 我想让一组左浮动div开始运行,水平放置一个带有水平滚动条的父div。 我可以在这里演示如何使用此糟糕的嵌入式CSS 但是,从SO *给出的答案来看,这应该可行,但对我而言却不可行。 有没有一种方法可以定义每个项目的绝对位置呢? eg [防止浮动的div包装到下一行 问题

  • 问题内容: 我在MySQL数据库架构中引入浮点列时遇到了一个问题,即对浮点值的比较不会总是返回正确的结果。 1-50.12 2-34.57 3-12.75 4-…(其余均小于12.00) 这将返回“ 3”。 我已经读过,在MySQL中比较浮点值是一个坏主意,十进制类型是更好的选择。 我是否有希望继续使用float类型,并使比较正常工作? 问题答案: 您是否注意到以下问题? 在某些行之间有一个额外的

  • 问题内容: 我正在开发需要检查作业截止日期的应用程序。我想知道到期日期是否在下个星期之内,然后再执行一项操作。 我可以找到的大多数文档都在Objective-C中,但我不知道如何在Swift中完成。谢谢您的帮助!! 问题答案: 我喜欢使用扩展使代码更具可读性。以下是一些NSDate扩展,它们可以帮助清理代码并使其易于理解。我把它放在一个sharedCode.swift文件中: 现在,如果您可以执行