使用非默认舍入模式将 long 转换为 double

Cast long to double with non-default rounding mode

在Java中,当 long 值转换为 double 值时,在无法进行无损转换时应用 IEEE754 舍入到最近的舍入模式。

例如,从 1L << 55(1L << 55) + 8 转换为 double 是无损的。但是,介于两者之间的任何数字都不能准确表示为 double。默认应用 IEEE-754 舍入到最近(与偶数相关)舍入模式。因此,(1L << 55) + 4) 或以下将向下舍入,而 (1L << 55) + 5 或以上将向上舍入。

标准库或番石榴中是否有任何函数允许我使用 Round toward +∞Round toward -∞ 模式(根据每个调用站点选择)将 long 转换为 double?假设没有,我如何高效地自己编写这两个函数?

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

这个怎么样:

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