在点后面的第16个元素处意外取整



可能重复:
在双中移动小数位数

我正在创建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

我不愿意添加这么多代码,但考虑到错误似乎是随机出现的(一次是在我添加生奶油时,一次是我创建巧克力+坚果时,两次是我添加糖霜时(,我真的无法确定我的代码中哪些部分相关,哪些部分不相关。

为什么它有时会对一个处处被声明为双的数字进行四舍五入,并且点后面总是有2位数字?

这就是浮点数(doublefloat(的实际情况。他们使用数学公式(我不详细说明(来存储数据,所以有些值并不是你所期望的那样(这就是为什么银行和其他货币系统使用BigDecimal而不是double或其他类似的东西(。

既然在你的情况下,你处理的是相当小的计量单位,我可能只会把它四舍五入到小数点后几位。

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

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

这只是浮点舍入的结果。请记住,在基数2中,一个漂亮的终止小数,如0.1,可能是一个无限重复的小数。当那个小数点四舍五入时,我们得到了这些奇怪的四舍五舍五入误差。

解决方案是永远不要直接打印浮点值。在Java.text中使用DecimalFormat或获取货币实例来格式化(并舍入(您的输出

最新更新