Есть ли функция, которая может конвертировать каждый дубль в уникальный uint64_t, сохраняя точность и порядок?(Почему я не могу найти один?) - PullRequest
0 голосов
/ 17 декабря 2018

Насколько я понимаю,

  • Двойные числа в C ++ (по крайней мере концептуально) кодируются как числа с плавающей запятой в кодировке IEEE 754 двойной точности.
  • IEEE 754 говорит, что такие числа могут быть представлены с помощью 64 бит.

Поэтому я должен ожидать, что существует функция f, которая может сопоставлять каждый дубль уникальному uint64_t, и этот порядок должен поддерживаться, а именно - для всех double lhs, rhs, lhs < rhs == f(lhs) < f(rhs)кроме случаев, когда (lhs или rhs равно NaN).

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

Я знаю, что простое деление на EPSILON не сработает, потому что точность на самом деле уменьшается по мере того, как числа становятся больше (и улучшается, когда числа очень близки к нулю);Тем не менее, я не совсем точно определил детали этого масштабирования.

Конечно, такая функция существует в принципе.

Разве я не нашел его, потому что он не может быть написан на стандартном C ++?Что это будет слишком медленно?Что это не так полезно для людей, как я думаю?

1 Ответ

0 голосов
/ 18 декабря 2018

Если представления 64-разрядных чисел с плавающей запятой IEEE-754 обрабатываются как 64-разрядные значения с двойным дополнением, эти значения имеют тот же порядок, что и соответствующие значения с плавающей запятой.Единственная задействованная корректировка - это ментальная, чтобы увидеть, как структура битов представляет либо значение с плавающей запятой, либо целочисленное значение.В CPU это просто: у вас есть 64 бита данных, хранящихся в памяти, и если вы применяете операцию с плавающей запятой к этим битам, вы выполняете операции с плавающей запятой, а если вы применяете целочисленные операции к этим битам, вы делаете целое числооперации.

В C ++ тип данных определяет тип операций, которые вы можете выполнять.Чтобы применить операции с плавающей точкой к 64-битному объекту данных, этот объект должен иметь тип с плавающей точкой.Для применения интегральных операций это должен быть целочисленный тип.

Для преобразования битовых комбинаций из числа с плавающей запятой в целое:

std::int64_t to_int(double d) {
    std::int64_t res
    std::memcpy(&res, &d, sizeof(std::int64_t));
    return res;
}

Преобразование в другом направлении оставлено в качестве упражнения длячитатель.

...