2

请有人帮我处理java浮点数。我观察到一些与 java 的不一致之处,例如

Math.pow(10.0,-2)==0.01
Math.pow(10.0,-3)=0.0010 (instead of 0.001)
Math.pow(10.0,-4)=1.0 E-4
printf("%g",Math.pow(10,-4)) =0.000100000 

而使用 Python:

10**-1=0.1
10**-2=0.01
10**-3=0.001

使用 Clojure 1.4

(Math/pow 10 -2) = 0.01
(Math/pow 10 -3) = 0.001

我的问题是如何在 Java 中获得类似的结果,与 Python 相比,换句话说,我如何获得没有任何尾随零的确切结果。为什么要添加这些尾随零,有什么方法可以抑制它们。

4

2 回答 2

5

很容易解释尾随零的来源。

因为%g它很简单:%g默认情况下总是显示 6 个有效数字,所以你会看到

1.00000
0.100000
0.0100000
0.00100000
0.000100000
1.00000e-5
1.00000e-6
...

您可以通过将精度设置为 1 个有效数字来消除它们,但您可能不想这样做,因为这也会将 2.5 舍入到 3,例如。

执行 aprintln直接显示结果 (a double) 的表示,如 定义Double.toString()

结果是一个字符串,表示参数的符号和大小(绝对值)。[...] 量级m

[...]

如果m大于或等于 10 -3但小于 10 7,则表示为m的整数部分,以十进制形式表示,不带前导零,后跟“.”。('\u002E'),后跟一个或多个小数位,表示m的小数部分。

[...]

如果m小于 10 -3或大于或等于 10 7,则它以所谓的“计算机科学计数法”表示。令n为唯一整数,使得 10 nm < 10 n +1;然后让am和 10 n的数学精确商,使得 1 ≤ a < 10。然后将大小表示为 a 的整数部分作为一个十进制数字,后跟“。” ('\u002E'),后跟表示 a 的小数部分的十进制数字,后跟字母 'E' ('\u0045'),后跟n表示为十进制整数,由方法 生成Integer.toString(int)

[...]

ma的小数部分必须打印多少位?必须至少有一个数字来表示小数部分,除此之外,必须有尽可能多的数字,但只需要将参数值与相邻的 double 类型值唯一区分开来。

因此你看到

1.0
0.01
0.0010
1.0E-4
9.999999999999999E-6
1.0E-6
...

那么如何摆脱尾随零呢?

一种方法是使用BigDecimal,它有一个stripTrailingZeros()方法。但是你必须小心你如何使用它:

System.out.println(BigDecimal.TEN.pow( -4 ,MathContext.DECIMAL64).stripTrailingZeros());

将打印预期的

0.0001

System.out.println(new BigDecimal(Math.pow(10,-4)).stripTrailingZeros());

将打印

0.000100000000000000004792173602385929598312941379845142364501953125

因为这恰好double是最接近 10 -4的确切值。

如果你不想在BigDecimals 中做所有的数学运算,那么你可以得到一个四舍五入结果的字符串表示形式%g(这让你有机会控制精度),从中得出一个BigDecimal结果,然后打印结果:

System.out.println(new BigDecimal( String.format("%g", Math.pow(10,-4) ) ).stripTrailingZeros());
于 2012-05-18T20:09:40.783 回答
0

如果您的问题只是显示,您可以使用 DecimalFormat 和 '#' http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html

于 2012-05-18T19:44:23.113 回答