使用BigDecimal非常大的数字

时间:2014-12-28 18:27:47

标签: java algorithm

我有这段代码:

while (counter <= t)
{
   a = a * counter;
   c = c * r + a;
   counter++;
}

我的t的值为101835

输出应为7.1 * 10 ^ 438,但NetBeans显示 输出为infinity

有什么东西可以将输出作为十进制数字吗?

2 个答案:

答案 0 :(得分:1)

IEEE-754定义的double不能代表这样的数字,它太大了。界限大约在-10 308 和10 308 之间。

您需要使用BigDecimal来表示它:一个具有任意字节数的数字来表示数字。

实现这一目标的更好方法:

double c = 0.0005d;//initialize c
double r = 0.01d;  //initialize r
double a = 0.0006d;//initialize a
BigDecimal abd = new BigDecimal(a); //BigDecimal for a
BigDecimal cbd = new BigDecimal(c); //BigDecimal for c
BigDecimal rbd = new BigDecimal(r); //BigDecimal for r
for (int counter = 1; counter <= t; counter++) {//perhaps other offset for counter?
   abd = abd.multiply(new BigDecimal(counter));
   cbd = cbd.multiply(rbd).add(abd);
}

这种方法的一个潜在问题是精度太高:Java将精确计算所有操作,导致数千位数。由于每次操作都会炸掉数字位数,在几次迭代中,简单的加法和乘法运算变得不可行。

您可以通过使用可选的MathContext参数定义精度来解决此问题:它确定结果的精确程度。例如,您可以使用MathContext.DECIMAL128

int t = 101835;
double c = 0.0005d;//initialize c
double r = 0.01d;  //initialize r
double a = 0.0006d;//initialize a
BigDecimal abd = new BigDecimal(a); //BigDecimal for a
BigDecimal cbd = new BigDecimal(c); //BigDecimal for c
BigDecimal rbd = new BigDecimal(r); //BigDecimal for r
for (int counter = 1; counter <= t; counter++) {//perhaps other offset for counter?
    abd = abd.multiply(new BigDecimal(counter),MathContext.DECIMAL128);
    cbd = cbd.multiply(rbd,MathContext.DECIMAL128).add(abd,MathContext.DECIMAL128);
}
System.out.println(abd);
System.out.println(cbd);

这给出了:

abd = 3.166049846031012773846494375835059E+465752
cbd = 3.166050156931013454758413539958330E+465752

这是近似正确的,因为a的所有结果应该是:

enter image description here

根据 Wolfram Alpha ,这是近似正确的。

此外,如果是for循环,我建议使用while而不是for。由于while倾向于创建另一种类型的无穷大:无限循环;)。

答案 1 :(得分:1)

是的,这里唯一应该使用的是BigDecimal类。它可以轻松处理复杂的价值,而不会给您带来负担。

支持的最大double值仅在1.7 * 10^ 308附近,由Java指定的Double.MAX_VALUE给出。