我尝试了以下代码.但是使用BigDecimal减去时会得到不同的结果.
double d1 = 0.1;
double d2 = 0.1;
System.out.println("double result: "+ (d2-d1));
float f1 = 0.1F;
float f2 = 0.1F;
System.out.println("float result: "+ (f2-f1));
BigDecimal b1 = new BigDecimal(0.01);
BigDecimal b2 = new BigDecimal(0.01);
b1 = b1.subtract(b2);
System.out.println("BigDecimal result: "+ b1);
Run Code Online (Sandbox Code Playgroud)
结果:
double result: 0.0
float result: 0.0
BigDecimal result: 0E-59
Run Code Online (Sandbox Code Playgroud)
我还在努力.任何人都可以澄清.
Oli*_*rth 11
[ 这里有很多答案告诉你二进制浮点不能完全代表0.01,并暗示你所看到的结果在某种程度上是不准确的.虽然第一部分是真的,但这并不是真正的核心问题.]
答案是"0E-59" 是等于0.回想一下,一个BigDecimal是未测量的值和小数比例因子的组合:
System.out.println(b1.unscaledValue());
System.out.println(b1.scale());
Run Code Online (Sandbox Code Playgroud)
显示:
0
59
Run Code Online (Sandbox Code Playgroud)
非标度值是 0,如所预期."奇怪的"比例值只是0.01的非精确浮点表示的十进制扩展的人为因素:
System.out.println(b2.unscaledValue());
System.out.println(b2.scale());
Run Code Online (Sandbox Code Playgroud)
显示:
1000000000000000020816681711721685132943093776702880859375
59
Run Code Online (Sandbox Code Playgroud)
下一个显而易见的问题是,为什么不方便BigDecimal.toString显示b1为" 0"?答案是字符串表示需要明确.来自JavadoctoString:
可区
BigDecimal分值与此转换结果之间存在一对一映射.也就是说,每个可区分的BigDecimal值(未缩放的值和比例)都具有作为使用结果的唯一字符串表示toString.如果BigDecimal使用BigDecimal(String)构造函数将该字符串表示转换回a ,则将恢复原始值.
如果它只是显示" 0",那么你将无法回到这个确切的BigDecimal对象.
小智 7
使用String中的构造函数: b1 = new BigDecimal("0.01");
(幻灯片23) http://strangeloop2010.com/system/talks/presentations/000/014/450/BlochLee-JavaPuzzlers.pdf
有趣的是,这些值似乎相等,而减法确实得到零,这似乎只是打印代码的问题。下面的代码:
import java.math.BigDecimal;
public class Test {
public static void main(String args[]) {
BigDecimal b1 = new BigDecimal(0.01);
BigDecimal b2 = new BigDecimal(0.01);
BigDecimal b3 = new BigDecimal(0);
if (b1.compareTo(b2) == 0) System.out.println("equal 1");
b1 = b1.subtract(b2);
if (b1.compareTo(b3) == 0) System.out.println("equal 2");
System.out.println("BigDecimal result: "+ b1);
}
}
Run Code Online (Sandbox Code Playgroud)
输出两条 equal消息,表明值相同并且您得到零并且相减时
您可以尝试将此作为错误提出,然后看看 Oracle 会返回什么结果。他们很可能只是声明0e-59仍然为零,因此不是错误,或者BigDecimal 文档页面上描述的相当复杂的行为正在按预期工作。具体来说,这一点指出:
可区分的 BigDecimal 值与此转换的结果之间存在一对一的映射。也就是说,由于使用 toString,每个可区分的 BigDecimal 值(未缩放值和小数位数)都具有唯一的字符串表示形式。如果使用 BigDecimal(String) 构造函数将该字符串表示形式转换回 BigDecimal,则将恢复原始值。
原始值需要可恢复这一事实意味着toString()需要为每个比例生成唯一的字符串,这就是您得到0e-59. 否则,将字符串转换回aBigDecimal可能会给出不同的值(未缩放值/缩放元组)。
如果您确实希望无论大小如何,零都显示为“0”,您可以使用类似以下内容的内容:
if (b1.compareTo(BigDecimal.ZERO) == 0) b1 = new BigDecimal(0);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9727 次 |
| 最近记录: |