Сравнение с плавающей точкой двойной точности - PullRequest
8 голосов
/ 14 ноября 2011

Я немного сбит с толку - будет ли сравнение чисел по-прежнему работать правильно, если они хранятся в виде непрозрачных (двоичных) полей?Проблема, с которой я сталкиваюсь, заключается в том, что в двойнике есть ведущий бит для знака (т.е. положительный или отрицательный), и когда они хранятся в виде двоичных данных, я не уверен, что они будут сравниваться правильно:*enter image description here

Я хочу убедиться, что сравнение будет работать правильно, потому что я использую двойной тип как часть набора ключей (например) в 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;
}

Ответы [ 3 ]

3 голосов
/ 14 ноября 2011

Создание моих комментариев как ответа.

Есть две вещи, которые могут пойти не так:

  1. Если один или оба параметра равны NAN, сравнения будутвсегда возвращать ложьТаким образом, даже если двоичное представление одинаково, NAN == NAN всегда будет ложным.Кроме того, это нарушает транзитивность сравнения.

  2. Если какой-либо из параметров не выровнен должным образом (так как они являются указателями на символы), вы можете столкнуться с проблемами на машинах, которые не поддерживают неправильный доступ к памяти,А для тех, кто это делает, вы можете столкнуться с падением производительности.

Поэтому, чтобы обойти эту проблему, вам нужно добавить случай прерывания, который будет вызываться, если какой-либо из параметров окажетсябыть NAN.(Я не уверен в статусе INF.)

Из-за необходимости в этом случае с ловушкой вам потребуется определить свой собственный оператор сравнения.

1 голос
/ 14 ноября 2011

Я предполагаю, что ваш числовой формат соответствует стандарту IEEE 754. Если это так, то простое сравнение со знаком и целым числом не будет работать - если оба числа отрицательны, результат сравнения переворачивается. Таким образом, вы должны предоставить свой собственный компаратор.

1 голос
/ 14 ноября 2011

Да, вы должны указать свою собственную функцию сравнения. Это связано с тем, что значения типа double не обязательно хранятся как значения с прямым порядком байтов. Показатель степени не будет храниться в памяти до мантиссы, хотя логически он появляется перед мантиссой, когда значение записывается в формате с прямым порядком байтов.

Конечно, если вы разделяете вещи между разными архитектурами ЦП в одной и той же базе данных, у вас могут возникнуть странные проблемы с порядком байтов в любом случае только потому, что вы хранили вещи как двоичные двоичные объекты.

Наконец, даже если бы вы могли контролировать порядок байтов, я бы все равно не доверял этому. Например, если двойное число не нормализовано, оно может некорректно сравниваться с другим двойным при сравнении в виде двоичных данных.

Конечно, все, что другой человек говорил о выравнивании и нечетных значениях, таких как NAN и INF, важно обратить внимание при написании функции сравнения. Но что касается того, стоит ли вам писать вообще, я бы сказал, что это будет действительно хорошая идея.

...