8

我在这里有点困惑 - 当双打存储为不透明(二进制)字段时,双打的比较仍然可以正常工作吗?我面临的问题是双精度包括符号的前导位(即正或负),当它们存储为二进制数据时,我不确定它是否会被正确比较:

在此处输入图像描述

我想确保比较能够正常工作,因为我在 LevelDB 中使用双精度作为键元组(例如)的一部分,并且我想保留正数和负数的数据局部性。LevelDB 仅使用不透明字段作为键,但它允许用户指定他/她自己的比较器。但是,我只想确保我不指定比较器,除非我绝对需要:

// Three-way comparison function:
//   if a < b: negative result
//   if a > b: positive result
//   else: zero result
inline int Compare(const unsigned char* a, const unsigned char* b) const 
{
    if (*(double*)a < *(double*)b) return -1;
    if (*(double*)a > *(double*)b) return +1;
    return 0;
}
4

3 回答 3

3

让我的评论成为答案。

有两件事可能会出错:

  1. 如果其中一个(或两个)参数为NAN,则比较将始终返回 false。所以即使二进制表示相同,NAN == NAN也永远是假的。此外,它违反了比较传递性。

  2. 如果任一参数未正确对齐(因为它们是 char 指针),您可能会在不支持未对齐内存访问的机器上遇到问题。对于那些这样做的人,您可能会遇到性能下降。

因此,要解决这个问题,您需要添加一个陷阱案例,如果任一参数结果为NAN. (我不确定 的状态INF。)

由于需要这种陷阱情况,您需要定义自己的比较运算符。

于 2011-11-14T05:57:21.687 回答
1

是的,您必须指定自己的比较函数。这是因为双精度不一定存储为“大端”值。指数不会在尾数之前驻留在内存中,即使当值以大端格式写出时,它在逻辑上出现在尾数之前。

当然,如果您在同一个数据库中的不同 CPU 架构之间共享内容,那么您最终可能会遇到奇怪的字节序问题,因为您将内容存储为二进制 blob。

最后,即使你可以控制字节顺序,我仍然不会相信它。例如,如果一个 double 未标准化,则在与二进制数据进行比较时,它可能无法正确地与另一个 double 进行比较。

当然,其他人所说的关于对齐和 NAN 和 INF 等奇数的所有内容在编写比较函数时都需要注意。但是,至于你是否应该写一个,我不得不说这将是一个非常好的主意。

于 2011-11-14T06:26:55.273 回答
1

我假设您的数字格式符合 IEEE 754 标准。如果是这种情况,那么简单的有符号整数比较将不起作用——如果两个数字都是负数,则比较的结果是相反的。所以你必须提供自己的比较器。

于 2011-11-14T07:40:57.000 回答