将浮点数的计算精度与x * 0.1和x / 10.0进行比较

时间:2015-10-03 15:33:35

标签: floating-point precision floating-accuracy numerical-methods

哪个表达更准确,为什么?我认为如果它不是10.0而且对于某个整数k它是2 ^ k,那么我们只需要在指数中减去k。但是有10个,我想不出比较它们的方法......

1 个答案:

答案 0 :(得分:1)

计算可以在java的BigDecimal中完成。所有有限双数都完全转换为BigDecimal。基于这两个想法,可以比较两种方法:

import java.math.BigDecimal;
import java.util.Random;

public class Test {
  public static void main(String[] main) {
    testDivide(1);
    testDivide(10);
    testDivide(1e6);
    Random rand = new Random(3);
    for(int i=0;i<1000000;i++){
      testDivide(rand.nextDouble());
    }
    System.out.println("Equal results: "+equals);
    System.out.println("Divide by 10 better: "+divBetter);
    System.out.println("Multiply by 0.1 better: "+multBetter);
  }

  private static int equals;
  private static int divBetter;
  private static int multBetter;

  public static void testDivide(double x) {
    BigDecimal tenth = new BigDecimal("0.1");
    double mult = x * 0.1;
    double div = x / 10;
    BigDecimal exact = new BigDecimal(x).multiply(tenth);
    BigDecimal multError = exact.subtract(new BigDecimal(mult)).abs();
    BigDecimal divError = exact.subtract(new BigDecimal(div)).abs();
    int comparison = divError.compareTo(multError);
    if(comparison == 0){
      equals++;
    } else if(comparison < 0){
      divBetter++;
    } else {
      multBetter++;
    }
  }
}

我得到了:

Equal results: 649781
Divide by 10 better: 350222
Multiply by 0.1 better: 0

正如@ n​​juffa的评论所暗示的那样,乘法方法永远不会更好。 10可以精确地表示为double,并且需要除以产生与实数除法的结果最接近的可表示数字。由于将0.1转换为double时固有的舍入误差,乘法方法可能无法得到最接近精确除法结果。