在Java中,当一个长值被投向双值时,当不可能进行无损转换时,会应用IEEE754舍入到最近的舍入模式。
例如,从 1L << 55
或 (1L << 55) + 8
到 double
是无损的。然而,任何介于两者之间的数字都不能准确地表示为 "无损"。double
. IEEE-754四舍五入模式是默认应用的。因此。(1L << 55) + 4)
或以下将四舍五入,如 (1L << 55) + 5
或向上将四舍五入。
在标准库或guava中是否有任何函数可以让我使用 Round toward +∞
或 Round toward -∞
模式(按每个呼叫点选择)?假设没有,我自己如何高效地写出这样两个函数?
这个怎么样。
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
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