我同意jmcnamara's prior answer。这个答案在此基础上展开。
对于每个 IEEE 754 64 位二进制浮点数,都有一个十进制小数范围,可以在输入时对其进行四舍五入。从-130.98999999999069开始,最接近的可表示值为-130.98999999999068677425384521484375。在四舍五入到最接近的四舍五入规则下,[-130.9899999999907009851085604168474674224853515625, -130.98999999999906725633991300128400325775146484375] 范围内的任何值都会舍入到该值。 (范围是封闭的,因为中心数的二进制表示是偶数。如果它是奇数,范围将是开放的)。 -130.98999999999069 和 -130.9899999999907 都在范围内。
你的浮点数确实和 Excel 一样。
您确实具有与 Excel 输入相同的浮点数。不幸的是,进一步的实验表明 Excel 2007 只转换输入的最重要的 15 位数字。我将 -130.98999999999069 粘贴到 Excel 单元格中。它不仅显示为 -130.98999999999,而且使用它的算术运算与最接近该值的双精度 -130.989999999990004653227515518665313720703125,而不是原始输入一致。
要获得与 Excel 相同的效果,您可能需要使用例如BigDecimal 截断为 15 位十进制数字,然后转换为双精度。
Java 对浮点值的默认字符串转换基本上选择小数位数最少的小数部分,这些小数部分将转换回原始值。 -130.9899999999907 的小数位数少于 -130.98999999999069。显然,Excel 显示的数字较少,但 Apache POI 正在获得与 Java 中相同数字的一种表示形式。
这是我用来获取此答案中数字的程序。请注意,我使用 BigDecimal 只是为了获得双打的精确打印输出,并计算两个连续双打之间的中点。
import java.math.BigDecimal;
class Test {
public static void main(String[] args) {
double d = -130.98999999999069;
BigDecimal dDec = new BigDecimal(d);
System.out.println("Printed as double: "+d);
BigDecimal down = new BigDecimal(Math.nextAfter(d, Double.NEGATIVE_INFINITY));
System.out.println("Next down: " + down);
System.out.println("Half down: " + down.add(dDec).divide(BigDecimal.valueOf(2)));
System.out.println("Original: " + dDec);
BigDecimal up = new BigDecimal(Math.nextAfter(d, Double.POSITIVE_INFINITY));
System.out.println("Half up: " + up.add(dDec).divide(BigDecimal.valueOf(2)));
System.out.println("Next up: " + up);
System.out.println("Original in hex: "+Long.toHexString(Double.doubleToLongBits(d)));
}
}
这是它的输出:
Printed as double: -130.9899999999907
Next down: -130.989999999990715195963275618851184844970703125
Half down: -130.9899999999907009851085604168474674224853515625
Original: -130.98999999999068677425384521484375
Half up: -130.9899999999906725633991300128400325775146484375
Next up: -130.989999999990658352544414810836315155029296875
Original in hex: c0605fae147ae000