考虑到我们不对浮点数进行任何操作,严格比较浮点数是否安全?

Is it safe to compare floats strictly, given we do no operations on them?

通常,当我们想要测试小数是否相等时,由于 IEEE754 的近似性质,我们这样做会有一定的不确定性。

if (fabs(one_float - other_float) < SUFFICIENTLY_SMALL) {
    consider them equal;
}

其他方法可能是将浮点数转换为特定大小的整数,然后比较结果整数。

if ((uint)one_float == (uint)other_float) {
    consider them equal;
}

但是请考虑我们的浮点数从不进行任何算术运算的情况,我们对它们所做的唯一事情就是赋值。

//  Might be called at any moment
void resize(float new_width, float new_height)
{
    if (current_width == new_width && current_height == new_height) {
        return;
    }

    accomodate framebuffers;
    update uniforms;
    do stuff;

    current_width = new_width;
    current_height = new_height;
}

在上面的示例中,我们有一个可能会自发启动的事件处理程序,并且我们希望仅在真正调整大小发生时才重新分配资源。我们可能会采用通常的方法进行近似比较,但这似乎是一种浪费,因为该处理程序会经常启动。据我所知,浮点数和其他所有东西一样,都是使用内存移动分配的;相等运算符只执行内存比较。所以看起来我们在一个安全的港湾。在 x86 和 ARM 上检查时,这个假设成立,但我只是想确定一下。也许它有一些规格支持?

那么,有没有什么东西可能只在分配时改变浮动?所描述的方法是否可行?

在这里查看如何比较两个浮点数。

https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

找到 "ULP, he said nervously" 的测试。您可以将浮点数与整数进行比较,但看看文章中是如何完成的(我希望我没有违反此处的任何许可,如果是这样,请删除后面的代码,这不是我的代码)

bool AlmostEqualUlps(float A, float B, int maxUlpsDiff){
    Float_t uA(A);
    Float_t uB(B);
    // Different signs means they do not match.
    if (uA.Negative() != uB.Negative()) {
        // Check for equality to make sure +0==-0
        if (A == B) {
            return true;
        }
        return false;
    }

    // Find the difference in ULPs.
    int ulpsDiff = abs(uA.i - uB.i);
    if (ulpsDiff <= maxUlpsDiff) {
        return true;
    }
    return false;
}

请阅读那篇文章的其余部分,它真的很棒。

在您提到的情况下,使用 == 进行比较是安全的,因为函数末尾有以下几行:

current_width = new_width;
current_height = new_height;

new_widthnew_height 的任何更改都将使 if 语句失败,您将获得所需的行为。

abs()函数通常用在程序中有一个动态赋值的变量float和一个常量float作为参考。类似于:

bool isEqual(float first, float second)
{
   if(fabs(first-second)<0.0001)
      return true;
   return false;
}

int main()
{
   float x = (float) 1 / 3;
   if(isEqual(x,0.3333))
      printf("It is equal\n");
   else
      printf("It is not equal\n");
}

接下来是 "should" 秒。

我认为没有任何内容表明从 float 到 float (current_width = new_width) 的赋值不能改变值,但如果存在这样的事情我会感到惊讶。除了直接复制之外,没有理由在相同类型的变量之间进行赋值。

如果传入的 new_widthnew_height 保持它们的值直到它们改变,那么这个比较应该没有任何问题。但是如果在每次调用之前计算它们,它们可能会改变它们的值,这取决于计算是如何完成的。所以需要检查的不仅仅是这个功能

C 2011 标准表示计算可能使用比您分配给的格式更高的精度,但没有具体说明将一个变量分配给另一个变量。所以唯一的不精确应该在计算阶段。 "simple assignment" 部分 (6.5.16.1) 说:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

所以如果类型已经匹配,应该不需要转换。

因此,简单地说:如果您不在每次调用时重新计算传入值,则相等比较 应该 成立。但是真的存在您的帧缓冲区大小为浮点数而不是整数的情况吗?