【effective java】48.正確な答えが必要な場合はfloatとdoubleの使用を避けてください

2390 ワード

floatとdoubleは主に科学計算とエンジニアリング計算のために設計され,二進浮動小数点演算を実行し,これは広範な数値範囲でより正確な高速近似計算を提供するために丹念に設計された.しかしながら、それらは完全に正確な結果を提供していないので、正確な結果が必要な場合、特に通貨計算には適していない.
public static void main(String[] args) {
    //   1.03 ,  0.42  
    System.out.println(1.03 - .42);//0.6100000000000001
    System.out.println(1.00 - 9 * .10);//0.09999999999999998
    System.out.println("=========");
    test1();
    System.out.println("=========");
    test2();
    System.out.println("=========");
    /**
     *   BigDecimal    :1.       ,   (    BigDecimal  );2.   
          int  long,          ,            ,     ,          ,     int   :
     */
    test3();
}
private static void test1() {
    // TODO Auto-generated method stub
    double funds = 1.00;
    int itemsBought = 0;
    for(double price = .10; funds >= price; price += .10) {
        funds -= price;
        itemsBought++;
        System.out.println("price:"+price+"funds:"+funds);
    }
    System.out.println(itemsBought + " items bought.");
    System.out.println("Money left over: $" + funds);
}

private static void test2() {
    final BigDecimal TEN_CENTS = new BigDecimal(".10");
    int itemsBought = 0;
    BigDecimal funds = new BigDecimal("1.00");
    for(BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) {
        itemsBought++;
        funds = funds.subtract(price);
        System.out.println("price:"+price+"funds:"+funds);
    }
    System.out.println(itemsBought + " items bought.");
    System.out.println("Money left over: $" + funds);

}


private static void test3() {
    // TODO Auto-generated method stub
    int itemsBought = 0;
    int funds = 100;
    for(int price = 10; funds >= price; price += 10) {
        itemsBought++;
        funds -= price;
        System.out.println("price:"+price+"funds:"+funds);
    }
    System.out.println(itemsBought + " items bought.");
    System.out.println("Money left over: $" + funds);
}

まとめ:正確な答えが必要な計算については、floatまたはdoubleを使用することはできません.BigDecimalは完全に切り込みを制御することができます.ビジネス要件が複数の切り込み方法に関連している場合は、BigDecimalを使用するのが便利です.パフォーマンスが重要で、関連する数値が大きくない場合は、intまたはfloatを使用することができます.数値範囲が9桁の10進数を超えていない場合は、intを使用することができます.18桁を超えない場合はlongを使用し、数値が18桁を超える可能性がある場合はBigDecimalを使用する必要があります.