Преобразование длинного в двойное с нестандартным режимом округления - PullRequest
3 голосов
/ 08 мая 2020

В Java, когда длинное значение преобразуется в двойное значение, применяется режим округления IEEE754 с округлением до ближайшего, когда преобразование без потерь невозможно.

Например, преобразование из 1L << 55 или от (1L << 55) + 8 до double без потерь. Однако любое промежуточное число не может быть точно представлено как double. По умолчанию применяется режим округления IEEE-754 с округлением до ближайшего (привязка к четному). В результате (1L << 55) + 4) или ниже будет округляться в меньшую сторону, а (1L << 55) + 5 или вверх будет округлено в большую сторону.

Есть ли какая-либо функция в стандартной библиотеке или гуаве, которая позволяет мне преобразовать длинное в двойное, используя * Режим 1011 * или Round toward -∞ (выбирается для каждого абонента)? Предполагая, что одной из них нет, как мне самому эффективно написать такие две функции?

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Как насчет этого:

static double longRoundUp(long lng)
{
    double d = (double)lng;     
    return lng <= (long)d ? d : Math.nextUp(d);
}

static double longRoundDown(long lng)
{
    double d = (double)lng;     
    return lng >= (long)d ? d : Math.nextDown(d);
}

Тест:

long l1 = (1L << 55);
long l2 = (1L << 55) + 8;
long l3 = (1L << 55) + 4;
long l4 = (1L << 55) + 5;

System.out.format("Up %d %.0f%n", l1, longRoundUp(l1));
System.out.format("Up %d %.0f%n", l2, longRoundUp(l2));
System.out.format("Up %d %.0f%n", l3, longRoundUp(l3));
System.out.format("Up %d %.0f%n", l4, longRoundUp(l4));

System.out.println();
System.out.format("Down %d %.0f%n", l1, longRoundDown(l1));
System.out.format("Down %d %.0f%n", l2, longRoundDown(l2));
System.out.format("Down %d %.0f%n", l3, longRoundDown(l3));
System.out.format("Down %d %.0f%n", l4, longRoundDown(l4));

Вывод:

Up 36028797018963968 36028797018963968
Up 36028797018963976 36028797018963976
Up 36028797018963972 36028797018963976
Up 36028797018963973 36028797018963976

Down 36028797018963968 36028797018963968
Down 36028797018963976 36028797018963976
Down 36028797018963972 36028797018963968
Down 36028797018963973 36028797018963968
2 голосов
/ 08 мая 2020

Math.nextUp() и Math.nextDown() могут помочь

long a = (1L<<55) + 4;       
long b = (1L<<55) + 5;       

double aa = (double)a;       
double bb = (double)b;       

System.out.println("aa = " +aa);
System.out.println("bb = " +bb); 

Печать

aa = 3.6028797018963968E16
bb = 3.6028797018963976E16
System.out.println("aa = " + Math.nextUp(aa));

Печать

aa = 3.6028797018963976E16

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...