Possible Duplicate:
Moving decimal places over in a double




我使用冰淇淋和补品作为主题,创建了Decorator模式的基本实现。一切正常,除了弹出的一些奇怪的输出行为。

在看似随机的地方,成本将在圆点后面的第16个元素处进行舍入,这很奇怪,因为我使用的数字是1.00(Vanilla),1.10(Chocolate),0.30(Sprinkles), 0.40(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


我不愿意添加这么多代码,但是考虑到错误似乎是随机弹出的(一次是当我添加鲜奶油时,当我创建巧克力+坚果时,一次是当我添加巧克力粉时),我无法真正查明我的哪个部分代码是相关的,什么是无关的。

为什么有时会四舍五入一个在各处都声明为双精度且始终在小数点后两位数字的数字?

最佳答案

这是浮点数(doublefloat)的现实。他们使用数学公式(我不详述)来存储数据,因此某些值与您期望的值不完全相同(这就是为什么银行和其他货币系统使用BigDecimal而不是double或其他这样的东西)。

由于在您的情况下,您正在使用较小的度量单位,因此我可能会将其四舍五入到小数点后一位。

这是要输出的一小段代码,四舍五入到小数点后两位:

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

09-29 19:45