大于1E22的BigDecimal精度



由于某种原因,我发现自己编写了一些软件,应该能够执行一些天文计算。虽然大部分内容都是关于将正确的公式转换到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);

最新更新