2013-01-12 39 views
0

可能重複:
Moving decimal places over in a double意外的舍入點後面

我創建Decorator模式的基本實現,用冰淇淋和補充爲主題。一切正常,除了一些奇怪的輸出行爲彈出。

在看似隨意地成本將與在該點後面的第16個元素0.40舍入,因爲我用的數字是1.00(Vanilla),這是不可思議,1.10(Chocolate),0.30(Sprinkles),輸出( WhippedCream)和0.35(Nuts)。

爲了重新創建你需要下面的類和接口:

public interface Icecream { 
    public double getCost(); 
    public String getDescription(); 
} 

public class Vanilla implements Icecream { 
    @Override 
    public double getCost() { 
     return 1.00; 
    } 

    @Override 
    public String getDescription() { 
     return "Vanilla ice"; 
    } 
} 

public class Chocolate implements Icecream { 
    @Override 
    public double getCost() { 
     return 1.10; 
    } 

    @Override 
    public String getDescription() { 
     return "Chocolate ice"; 
    } 
} 

public abstract class Decorator implements Icecream{ 
    protected Icecream decoratedIcecream; 

    public Decorator(Icecream decoratedIcecream) { 
     this.decoratedIcecream = decoratedIcecream; 
    } 

    public abstract double getCost(); 
    public abstract String getDescription(); 
} 

public class Sprinkles extends Decorator { 
    public Sprinkles(Icecream decoratedIcecream) { 
     super(decoratedIcecream); 
    } 

    @Override 
    public double getCost() { 
     return decoratedIcecream.getCost() + 0.30; 
    } 

    @Override 
    public String getDescription() { 
     return decoratedIcecream.getDescription() + ", Sprinkles"; 
    } 
} 

public class WhippedCream extends Decorator { 
    public WhippedCream(Icecream decoratedIcecream) { 
     super(decoratedIcecream); 
    } 

    @Override 
    public double getCost() { 
     return decoratedIcecream.getCost() + 0.40; 
    } 

    @Override 
    public String getDescription() { 
     return decoratedIcecream.getDescription() + ", Whipped cream"; 
    } 
} 

public class Nuts extends Decorator { 
    public Nuts(Icecream decoratedIcecream) { 
     super(decoratedIcecream); 
    } 

    @Override 
    public double getCost() { 
     return decoratedIcecream.getCost() + 0.35; 
    } 

    @Override 
    public String getDescription() { 
     return decoratedIcecream.getDescription() + ", Nuts"; 
    } 
} 


public class StartUp { 
    public static void main(String[] args) { 
     Icecream icecream = new Vanilla(); 
     showDetails(icecream); 

     icecream = new Sprinkles(icecream); 
     showDetails(icecream); 

     icecream = new WhippedCream(icecream); 
     showDetails(icecream); 

     Icecream icecream2 = new Nuts(new Chocolate()); 
     showDetails(icecream2); 

     icecream2 = new Sprinkles(icecream2); 
     showDetails(icecream2); 

     Icecream icecream3 = new Vanilla(); 
     showDetails(icecream3); 

     icecream3 = new Nuts(icecream3); 
     showDetails(icecream3); 

     icecream3 = new Sprinkles(icecream3); 
     showDetails(icecream3); 
    } 

    private static void showDetails(Icecream icecream){ 
     System.out.println("Cost: " + icecream.getCost() + "\t" + "Description: " + icecream.getDescription()); 
    } 
} 

導致下面的輸出:

Cost: 1.0 Description: Vanilla ice 
Cost: 1.3 Description: Vanilla ice, Sprinkles 
Cost: 1.7000000000000002 Description: Vanilla ice, Sprinkles, Whipped cream 
Cost: 1.4500000000000002 Description: Chocolate ice, Nuts 
Cost: 1.7500000000000002 Description: Chocolate ice, Nuts, Sprinkles 
Cost: 1.0 Description: Vanilla ice 
Cost: 1.35 Description: Vanilla ice, Nuts 
Cost: 1.6500000000000001 Description: Vanilla ice, Nuts, Sprinkles 

我捨不得添加這麼多的代碼,但考慮到錯誤似乎隨機彈出(一次當我添加奶油,當我創建巧克力+堅果,兩次當我添加灑)我不能真正查明我的代碼的哪些部分是相關的,哪些不是。

爲什麼它有時會將一個數字宣告爲無處不在,並且始終在點後面有兩位數字?

回答

4

這是浮點數的現實(doublefloat)。他們使用數學公式(我沒有詳細說明)來存儲他們的數據,所以一些數值並不完全符合您的預期(這就是爲什麼銀行和其他貨幣系統使用BigDecimal而不是double或其他類似的東西)。

因爲,在你的情況下,你正在處理相當小的度量單位,我可能只是將其舍入到小數位。

這裏的代碼輸出小一點,四捨五入至小數點後2位:

String dblOutput = new DecimalFormat("#.##").format(icecream.getCost()); 
System.out.println("Cost: " + dblOutput + "\t" + "Description: " + icecream.getDescription()); 
1

這僅僅是浮點舍入的結果。請記住,在基數2中,一個很好的終止小數,如0.1可能是一個無限重複小數。當小數點四捨五入時,我們會得到這些奇怪的四捨五入錯誤。

解決方法是不要直接打印浮點值。在Java.text中使用DecimalFormat或獲取貨幣實例來格式化(和舍入)您的輸出