精度丢失时的Java数学

时间:2015-12-28 12:45:32

标签: java math

以下算法用于识别较小数字的因子,但在使用较大的数据时会完全失败,例如7534534523.0

double result = 7; // 7534534523.0;

double divisor = 1;

for (int i = 2; i < result; i++){

   double r = result / (double)i;

   if (Math.floor(r) == r){
      divisor = i;
      break;
   }
}


System.out.println(result + "/" + divisor + "=" + (result/divisor));

计算器上的数字7534534523.0除以2可以给出小数部分或舍入它(丢失0.5)。如何对大数字进行检查?我必须使用BigDecimal吗?或者还有另一种方式吗?

3 个答案:

答案 0 :(得分:3)

如果您的目标是在小数点右侧表示具有完全n个有效数字的数字,则BigDecimal是要使用的类。

  

不可变,任意精度的带符号十进制数。 BigDecimal由任意精度整数非标度值和32位整数标度组成。如果为零或正数,则比例是小数点右侧的位数。如果是负数,则将数字的未缩放值乘以10来表示比例的否定。因此,BigDecimal表示的数字的值是(unscaledValue×10-scale)。

此外,您可以更好地控制缩放操作,舍入和格式转换。

答案 1 :(得分:1)

我看不出你的代码中存在什么问题。它的工作原理与应有的完全相同 当我运行你的代码时,我得到了这个输出:

7.534534523E9/77359.0=97397.0

这可能让你困惑,但它完全没问题。它只是使用科学记数法,但没有错。

7.534534523E9 = 7.534534523 * 10 9 = 7,534,534,523

如果您想以正常表示法看到它,可以使用System.out.format打印结果:

System.out.format("%.0f/%.0f=%.0f\n", result, divisor, result / divisor);

节目:

7534534523/77359=97397

但是你不需要double或BigDecimal来检查一个数字是否可以被另一个数字整除。您可以对整数类型使用模运算符来检查一个数字是否可被另一个数整除。只要您的数字适合long,这就有效,否则您可以转到BigInteger

long result = 7534534523L;
long divisor = 1;
for (int i = 2; i < result; i++) {
    if (result % i == 0) {
        divisor = i;
        break;
    }
}
System.out.println(result + "/" + divisor + "=" + (result / divisor));

答案 2 :(得分:0)

BigDecimal是保持数字高精度的方法。

DO NOT 不使用构造函数BigDecimal(double val),因为执行舍入并且输出并不总是相同。同样是mentioned in the implementation。根据它:

  

这个构造函数的结果可能有些不可预测。有人可能会假设在Java中编写新的BigDecimal(0.1)会创建一个BigDecimal,它恰好等于0.1(未缩放值为1,标度为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能精确地表示为double(或者,就此而言,作为任何有限长度的二进制分数)。因此,传递给构造函数的值并不完全等于0.1,尽管有外观。

总是尝试使用构造函数BigDecimal(String val),因为它保留了精度并且每次都提供相同的输出。