gpt4 book ai didi

java - 在Java中匹配Excel的 float

转载 作者:搜寻专家 更新时间:2023-10-30 19:57:49 29 4
gpt4 key购买 nike

我有一个 .xlsx 电子表格,在工作表 1 的左上角单元格中有一个数字。

Excel 用户界面显示:

-130.98999999999

这在公式栏中可见,即不受包含单元格设置为显示的小数位数的影响。这是 Excel 将为此单元格显示的最准确的数字。

在底层 XML 中,我们有:

<v>-130.98999999999069</v>

当尝试使用 Apache POI 读取工作簿时,它通过 Double.valueOf 从 XML 中获取数字并得出:

-130.9899999999907

不幸的是,这与用户在 Excel 中看到的数字不同。任何人都可以指出一种算法来获得用户在 Excel 中看到的相同数字吗?

到目前为止,我的研究表明 Excel 2007 文件格式使用了略微非标准的 IEE754 浮点版本,其中值空间不同。我相信 Excel 的 float ,这个数字落在四舍五入边界的另一边,因此结果好像向下而不是向上舍入。

最佳答案

我同意 jmcnamara's prior answer .这个答案对此进行了扩展。

对于每个 IEEE 754 64 位二进制 float ,都有一系列小数可以在输入时四舍五入。从 -130.98999999999069 开始,最接近的可表示值是 -130.98999999999068677425384521484375。根据四舍五入到最接近的四舍五入规则,[-130.9899999999907009851085604168474674224853515625, -130.9899999999906725633991300128400325775146484375] 范围内的任何内容四舍五入到该值。 (范围是封闭的,因为中心数的二进制表示是偶数。如果是奇数,范围将是开放的)。 -130.98999999999069 和 -130.9899999999907 都在范围内。

您确实拥有与 Excel 相同的 float 。您确实具有与输入到 Excel 中的 float 相同的 float 。遗憾的是,进一步的实验表明 Excel 2007 仅转换输入中最重要的 15 位数字。我将 -130.98999999999069 粘贴到 Excel 单元格中。它不仅显示为 -130.98999999999,而且使用它的算法与最接近该值的 double 值 -130.989999999990004653227515518665313720703125 一致,而不是原始输入。

要获得与 Excel 相同的效果,您可能需要使用例如BigDecimal 截断为 15 位十进制数字,然后转换为 double 。

Java 对浮点值的默认字符串转换基本上会选择小数位数最少的小数,然后再转换回原始值。 -130.9899999999907 的小数位数少于 -130.98999999999069。显然,Excel 显示的数字较少,但 Apache POI 得到的是与 Java 中相同数字的表示之一。

这是我用来获取此答案中数字的程序。请注意,我使用 BigDecimal 只是为了获得 double 的精确打印输出,并计算两个连续 double 之间的中点。

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

关于java - 在Java中匹配Excel的 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28537614/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com