在非默认四舍五入模式下长投双倍。

问题描述 投票:0回答:1

在Java中,当一个长值被投向双值时,当不可能进行无损转换时,会应用IEEE754舍入到最近的舍入模式。

例如,从 1L << 55(1L << 55) + 8double 是无损的。然而,任何介于两者之间的数字都不能准确地表示为 "无损"。double. IEEE-754四舍五入模式是默认应用的。因此。(1L << 55) + 4) 或以下将四舍五入,如 (1L << 55) + 5 或向上将四舍五入。

在标准库或guava中是否有任何函数可以让我使用 Round toward +∞Round toward -∞ 模式(按每个呼叫点选择)?假设没有,我自己如何高效地写出这样两个函数?

java ieee-754
1个回答
2
投票

这个怎么样。

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
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.