当前位置: 首页 > 面试题库 >

匹配Java中的Excel浮点

邬宜然
2023-03-14
问题内容

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

Excel UI显示:

-130.98999999999

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

在基础XML中,我们有:

<v>-130.98999999999069</v>

当尝试使用Apache POI读取工作簿时,它通过Double.valueOf从XML中输入数字,并提供:

-130.9899999999907

不幸的是,这与用户在Excel中看到的数字不同。谁能指出我的算法来获得用户在Excel中看到的相同数字?

到目前为止,我的研究表明Excel
2007文件格式使用的是IEE754浮点格式,它的值空间有所不同,该格式略有非标准。我相信Excel的浮点数会落在边界的另一边进行舍入,因此好像舍入而不是舍入。


问题答案:

我同意mcnamara的先前回答。这个答案就此展开。

不幸的是,这与用户在Excel中看到的数字不同。谁能指出我要使用一种算法来获得用户在Excel中看到的相同数字?

我认为这里没有使用算法。Excel在内部使用IEEE754 double,并且我猜它printf在显示数字时仅使用一种样式格式:

$ python -c 'print "%.14g" % -130.98999999999069' 
-130.98999999999

$ python -c 'print "%.14g" % -130.9899999999907' 
-130.98999999999

对于每个IEEE 754
64位二进制浮点数,在输入时会有一个十进制小数范围会四舍五入。从-130.98999999999069开始,最接近的可表示值为-130.98999999999068677425384521484375。在使用半舍入四舍五入规则进行四舍五入到最接近的情况下,[-130.9899999999907009851085604168474674274224853515625,-130.9899999999906725633991300128400325775146484375]范围内的任何内容都会四舍五入到该值。(该范围是封闭的,因为中心数字的二进制表示形式是偶数。如果它是奇数,则该范围将是开放的)。-130.98999999999069和-130.9899999999907都在范围内。

您确实具有与Excel相同的浮点数。 您确实具有与输入到Excel相同的浮点数。不幸的是,进一步的实验表明Excel
2007只能转换输入的最高15位数字。我将-130.98999999999069粘贴到Excel单元格中。它不仅显示为-130.98999999999,使用它的算术运算还与最接近该值的双精度数-130.989999999990004653227515518665313720703125一致,而不是原始输入。

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

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


 类似资料:
  • 问题内容: 我正在编写一个简单的调试程序,该程序将简单的字符串作为输入,其中可以包含星号以指示通配符匹配-任何 我以为我会简单地采用该模式,转义其中的任何正则表达式特殊字符,然后将其替换为。然后使用正则表达式匹配器。 但是我找不到任何Java函数来转义正则表达式。我能找到的最佳匹配,然而这正好将与在开始和字符串的结尾。 Java中有什么可以让您简单地进行通配符匹配而不必从头开始实现算法的? 问题答

  • 问题内容: 任何人都可以取悦我,为什么以下程序的输出不是“不同”? o / p:不同 问题答案: 6.5具有有限的二进制表示形式:110.1 具有至少4个有效位的任何浮点类型都可以完美地表示该数字。 110.100000000000000000000(浮点) = 6.5 110.100000000000000000000000000000000000000000000000000000000000

  • 问题内容: 在尝试使用Maven 在命令行上 构建应用程序时,我遇到了一个奇怪的问题。(我在SO上看到的其他问题是指在Eclipse或其他一些IDE中进行构建) 当我尝试构建时,maven抱怨它无法在tools.jar中找到Javac。查看给定的位置,很明显Maven正在JRE目录中,但是,我似乎无法让Maven指向我的JDK的正确Java_home- 关于如何执行此操作的任何想法? 环境概况 欢

  • 因此,我想在一个泛型类列表中交叉匹配数据,其中需要检查名称与姓氏的匹配,如果存在匹配,则返回数据或返回布尔值。这是我想到的 这返回TRUE,因为我使用GETTER AND SETTER通过设置布尔值从lambda表达式返回布尔值。 所以我在寻找最简单的lambda表达式来实现这一点?请问外面有人吗。

  • 我在做一个匹配的纸牌游戏,但我不明白如何实际做到这一点。我希望有人能帮我解释一下我能做些什么来解决这个问题。 以下是规格: 在一个对的纸牌游戏中,目标是翻出对匹配的纸牌。 https://en.wikipedia.org/wiki/contension_(游戏)以下是我们考虑的配对变化的规则。 在游戏开始时,有n张牌面朝下,其中n是4的倍数。每种卡片有4张,卡片上标有字母a、b、....例如,如果

  • Soap请求生成的Java应用程序[失败] SoapUI生成的Soap请求[成功] 如何将命名空间 uri “http://schemas.xmlsoap.org/soap/envelope/” 更改为“http://www.w3.org/2003/05/soap-envelope”。我没有创建任何客户端,我刚刚创建了java类并运行,由于上面的uri链接,我能够发送请求并获得错误代码响应。我发现