由于某种原因,我发现自己编写了一些软件,应该能够执行一些天文计算。虽然大部分内容都是关于将正确的公式转换到Java中,但我在"测试如何计算大数"的一开始就发现了一个恼人的问题。
嗯…想象一下太阳(我们的太阳),它的质量是(为了更容易解释,大约是圆形的)10E30千克。10后面跟着30。所有本机数据类型都不能用于此。值得一提的是:我知道我可以使用3000来计算东西,只在输出视图中添加末尾的零,但我希望尽可能保持精确。所以使用短号码将是我最后的手段。
问题来了。请看下面的代码:
BigDecimal combinedMass = new BigDecimal(1E22);
int massDistribution = 10;
Integer mD1 = massDistribution;
Integer mD2 = 100 - massDistribution;
BigDecimal starMass;
BigDecimal systemMass;
systemMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD1.toString()));
starMass = combinedMass.divide(new BigDecimal("100")).multiply(new BigDecimal(mD2.toString()));
System.out.println((systemMass).toEngineeringString());
System.out.println((starMass));
它将输出1000000000000000000000和90000000000000000000000000,这正是我所期望的。但是看看combemass字段。如果我将它提高到1E23,输出将改变
得到999999999999999999161139.20和899999999999999999992450252.80…
所以我知道我可以只使用BigInteger,因为它在这种情况下更可靠,但是为了精度,有时BigWhatEver可能会下降到像50.1258这样的值另外,我希望能得10分。xE30作为输出,只有使用bigDecimals才能实现。
我想知道:有没有办法避免这种情况(错误超过1E23的每一个值我尝试),同时保持计算浮点数的能力?我应该将此字段的后小数分隔符值切割为两个数字吗?
还有更多的疑问:
System.out.println(combinedMass.precision());
与上述代码的关系将为这种情况提供23,但对于大多数其他值提供En+1(这是当我变得真正困惑时)
谢谢你的建议
您正在使用基本类型而没有意识到这一点:
new BigDecimal(1E22);
这里,1E22是一个基本双精度类型,使用它已经失去了精度。
你想要的是
new BigDecimal("10000000000000000000000");
或
new BigDecimal(10).pow(22);