Java с плавающей точкой двойных - верхних и нижних границ? - PullRequest
4 голосов
/ 25 ноября 2011

Как известно большинству здесь, double -> float приводит к потере точности. Это означает, что множественные двойные значения могут быть сопоставлены одному и тому же значению с плавающей запятой. Но как мне пойти другим путем? Учитывая нормальное (я не забочусь о крайних случаях) с плавающей точкой, как мне найти верхнее и нижнее значение двойной точности, которые по-прежнему отображаются на тот же с плавающей точкой?

Или, чтобы говорить в коде:

function boolean testInterval(float lowF, float highF, double queryD) {
    float queryF = (float) queryD;
    return (lowF <= queryF) && (queryF <= highF);
}

и

function boolean testInterval(float lowF, float highF, double queryD) {
    double lowD = (double) lowF;
    double highD = (double) highF;
    return (lowD <= queryD) && (queryD <= highD);
}

не всегда дает одинаковый результат. Я ищу две функции float-> double, чтобы вторая функция возвращала тот же результат в первой.

Это может сработать, но для меня это похоже на взлом, а не правильное решение.

function boolean testIntervalHack(float lowF, float highF, double queryD) {
    double lowD = (double) lowF - Float.MIN_VALUE;
    double highD = (double) highF + Float.MIN_VALUE;
    return (lowD <= queryD) && (queryD <= highD);
}

1 Ответ

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

Ваш testIntervalHack не работает, диапазон значений double, сопоставляемых с одним и тем же float, варьируется. Например, при x = 2^24-1 каждый double между x-0.5 и x+0.5 будет отображаться на одно и то же значение (значение float x), но x +/- Float.MIN_VALUE == x.

Мне неизвестны какие-либо удобные методы API, поэтому лучшее, что я могу предложить, это

  1. преобразовать в double
  2. преобразовать double в представление битов с помощью doubleTo(Raw)LongBits
  3. добавить или вычесть один из 2 28 или 2 28 -1, в зависимости от того, хотите ли вы верхнюю или нижнюю границу и 2 29 -бит равно 0 или 1 (из-за округления до четного)
  4. конвертировать это длинное в удвоенное значение с помощью longBitsToDouble

Ну, это для конечных значений в диапазоне float. Для NaN с вы можете остановиться после шага 1. для бесконечностей это немного более деликатно, поскольку значения double больше или равны 2 128 -2 103 преобразуются в (float)Infinity, что немного отличается от битового представления (double)Infinity.

...