当前位置: 首页 > 知识库问答 >
问题:

比较浮点值有多危险?

戚飞虎
2023-03-14

我知道uikit使用cgfloat是因为分辨率无关的坐标系。

if (theView.frame.origin.x == 0) {
    // do important operation
}

cgfloat==,<=,>=,<,比较时不是容易出现误报吗?它是一个浮点,它们有不精确的问题:例如0.0000000000041

Objective-C在比较时是否在内部处理这个问题,或者是否会发生读取为零的Origin.x0不比较为true的情况?

共有1个答案

谷梁星雨
2023-03-14

首先,浮点值的行为并不是“随机”的。精确的比较在很多实际应用中都是有意义的。但是如果你要使用浮点,你需要知道它是如何工作的。假设浮点像实数一样工作的错误将会得到快速崩溃的代码。假设浮点结果有很大的随机模糊(就像这里的大多数答案所建议的那样)这一点上的错误将会得到一个代码,一开始看起来是可以工作的,但最后却有很大的错误和断角情况。

首先,如果你想用浮点编程,你应该读到这一点:

关于浮点算术,每个计算机科学家都应该知道些什么

>

  • 您可能在源代码中写入或使用scanfstrtod读入的许多值并不是浮点值,而是以静默方式转换为最接近的近似值。这就是demon9733的答案所说的。

    由于没有足够的精确度来表示实际结果,许多结果被四舍五入。您可以看到这一点的一个简单示例是将x=0x1fffffey=1添加为浮点。在这里,x的尾数(ok)精度为24位,y只有1位,但当您将它们相加时,它们的位不在重叠的地方,结果需要25位精度。相反,它会被舍入(默认舍入模式下为0x2000000)。

    许多结果由于需要无限多的位置才能得到正确的值而四舍五入。这包括有理的结果,比如1/3(你们熟悉的小数,它需要无限多位),也包括1/10(它在二进制中也需要无限多位,因为5不是2的幂),还有无理的结果,比如任何不是完全平方的东西的平方根。

    双舍入。在某些系统(特别是x86)上,浮点表达式的计算精度高于其标称类型。这意味着,当发生上述类型的舍入时,您将获得两个舍入步骤,首先将结果舍入到更高精度的类型,然后舍入到最终类型。例如,考虑一下如果将1.49舍入为整数(1),十进制会发生什么,而如果首先将其舍入为小数点后一位(1.5),然后将结果舍入为整数(2)会发生什么。这实际上是浮点处理中最棘手的领域之一,因为编译器的行为(特别是对于bug的、不符合要求的编译器,如GCC)是不可预测的。

    未指定超越函数(trigexplog等)具有正确舍入的结果;结果只是指定在最后一个精度位置的一个单位内是正确的(通常称为1ULP)。

    当您编写浮点代码时,您需要记住您在处理可能导致结果不精确的数字时所做的操作,并相应地进行比较。通常,与“epsilon”进行比较是有意义的,但epsilon应该基于所比较的数字的大小,而不是一个绝对常数。(在绝对常数epsilon可以工作的情况下,这强烈地表明固定点(而不是浮点)才是该工作的正确工具!)

    编辑:特别是,幅度相对的epsilon检查应该类似于:

    if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y))
    

    其中flt_epsilonfloat.h中的常量(用dbl_epsilon替换dbl_epsilon表示doubles,用ldbl_epsilon表示long double),而k是您选择的常量,这样您的计算的累积误差肯定是由k单元在最后一个位置限定的(如果您不确定错误界限计算是否正确,请将

    最后,请注意,如果您使用它,在零附近可能需要一些特别的注意,因为flt_epsilon对于反正规没有意义。一个快速的解决办法是:

    if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y) || fabs(x-y) < FLT_MIN)
    

    如果使用double,则同样替换dbl_min

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

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

    • 在C中,如果我们执行以下代码: 上面的代码打印“更少”。 但如果我们执行以下代码: 它打印“否”。 原因是什么?浮点数据类型是如何工作的?

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

    • 问题内容: 我想比较PHP中的两个浮点数,如以下示例代码所示: 在此代码中,即使和相同,它也返回条件的结果而不是条件。有没有什么特殊的方法来处理/比较PHP中的浮点数? 如果是,那么请帮助我解决此问题。 还是我的服务器配置有问题? 问题答案: 如果您这样做,它们 应该 是相同的。但是请注意,浮点值的一个特征是 看起来 可以导致相同值的计算实际上不必相同。因此,如果是一个文字并通过计算到达该文字,则

    • 我正试图在Linux中实现这一点 我面临着几个问题: 处理浮点数 比较(使用$vs不使用) 计算绝对值 我不能一次解决我的问题并处理所有这些问题。我已经搜索了很多很多页面,有些解决方案不适合我。例如,我似乎没有腹肌功能。 任何帮助都将不胜感激。