【问题标题】:Are two doubles of equal value guaranteed to have the same bit pattern?两个相等值的双精度是否保证具有相同的位模式?
【发布时间】:2016-10-07 03:06:39
【问题描述】:

在 C 中,是否可以保证两个值相等的双精度 (double1 == double2) 具有相同的位模式?

【问题讨论】:

  • 这不是语言的问题,而是 pc 架构本身的问题。如果你喜欢它,你可以阅读数值分析,无论如何只要记住,在比较浮点数时,你应该检查它们的差异是否可以忽略不计的值。该值应该对您的应用程序有意义,即虽然比较 |a - b| 确实有意义
  • 注意:即使double:+0.0 和-0.0 相同,某些操作会给出不同的结果:What operations and functions on +0.0 and -0.0 give different arithmetic valued results?
  • 我闻到了 XY 问题。 为什么你要依赖它?
  • 我正在创建一个类似 JVM 的小型字节码解释器,在其中我使用 NaN 标记将双精度值和指向对象的指针存储在 uint64_t 中。显然,相等的位模式可以保证数字和对象的平等,但是如果数字的位模式可以不同而值保持不变,那么我显然不能只依赖位模式。
  • 只记得 NaN 无论如何都不会相等。

标签: c floating-point bit-manipulation


【解决方案1】:

没有这样的保证。

例如IEEE floating point format中,存在负0的概念。它比较等于正0,但表示不同。

这是一个例子:

#include <stdio.h>

int main()
{
    unsigned long long *px, *py;
    double x = 0.0, y = -0.0;
    px = (unsigned long long *)&x;
    py = (unsigned long long *)&y;

    printf("sizeof(double)=%zu\n",sizeof(double));
    printf("sizeof(unsigned long long)=%zu\n",sizeof(unsigned long long));

    printf("x=%f,y=%f,equal=%d\n",x,y,(x==y));
    printf("x=%016llx,y=%016llx\n",*px,*py);

    return 0;
}

输出:

sizeof(double)=8
sizeof(unsigned long long)=8
x=0.000000,y=-0.000000,equal=1
x=0000000000000000,y=8000000000000000

编辑:

这是一个不依赖类型双关语的修改示例:

#include <stdio.h>

void print_bytes(char *name, void *p, size_t size)
{
    size_t i;
    unsigned char *pdata = p;
    printf("%s =", name);
    for (i=0; i<size; i++) {
        printf(" %02x", pdata[i]);
    }
    printf("\n");
}

int main()
{
    double x = 0.0, y = -0.0;

    printf("x=%f,y=%f,equal=%d\n",x,y,(x==y));
    print_bytes("x", &x, sizeof(x));
    print_bytes("y", &y, sizeof(y));

    return 0;
}

输出:

x=0.000000,y=-0.000000,equal=1
x = 00 00 00 00 00 00 00 00
y = 00 00 00 00 00 00 00 80

您可以在这里看到两者在表示上的差异。一个设置了符号位,而另一个没有设置。

【讨论】:

  • 注意:对于各种 IEEE 十进制 FP 格式,有许多具有相同值的冗余位模式。例如。 decimal64 floating-point format
  • 请注意,-0.0 不能保证实际给出负零
  • 请注意,您不应通过取消引用键入双关语,因为这会破坏严格的别名。从 C99 开始,您可以使用 memcpy 或 unions。
【解决方案2】:

是的,除了零。只有一种方法可以表示特定的 IEEE 浮点或双精度值。如果有两种方法来表示相同的值,那将是一种浪费,而且 IEEE 格式非常有效。

零是一种特殊情况,因为零有正值和负值,它们比较相等,并且在大多数情况下它们是相等的。在极少数情况下 (1/0),它们会给出不同的结果 - 正无穷与负无穷。

上一个答案不必要地集中在零案例上,据我所知,未能回答其他 40 亿个浮点数和 160 亿个双精度数的案例。

【讨论】:

  • 那么 +0 和 -0 是该规则唯一可能的例外情况?
  • 有些几何中 +infinity 和 -infinity 被认为是相等的,但 IEEE 数学并不这样对待它们。还有一些 NaN 被认为不等于一切,甚至它们自己。所以是的,+0 和 -0 是唯一的例外。
猜你喜欢
  • 1970-01-01
  • 2019-03-27
  • 2021-10-21
  • 2015-05-17
  • 1970-01-01
  • 2017-11-02
  • 2016-02-16
  • 2011-06-14
  • 1970-01-01
相关资源
最近更新 更多