使用非默认舍入模式将 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
在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