收银机计算问题|爪哇

时间:2021-02-09 19:00:37

标签: java logic project

编辑:一个可能的解决方案: 我试图打印剩余的,我得到了这个: 3.75 1.75 0.75 0.25 0.049999997 0.029999997 0.009999998

0.04 和 0.02 我想是问题所在!


我的问题:

我必须用java写一个收银程序——我做的收银机只有以下注释:

  • 一法郎:.01
  • 两个法郎:.02
  • 五法郎:0.05
  • 十法郎:.10
  • 二十法郎:0.20
  • 五十法郎:0.50
  • 一生丁:1
  • 两生丁:2
  • 五生丁:5
  • 十生丁:10
  • 二十生丁:20
  • 五十生丁:50

例如:

输入:

price = 11.25
cash = 20 

输出:

Five Francs, Two Francs, One Franc, Fifty Centimes, Twenty Centimes, Five Centimes

我的问题是我的代码给了我这个输出:

Five Francs, Teo Francs, One Franc, Fifty Centimes, Twenty Centimes, Two Centimes, Two Centimes

注意我如何得到 2 个二生丁而不是五生丁 所以我还差 1 生丁。


我用一个简单的循环和枚举解决了这个问题:

我的枚举:

public enum bill {
    Fifty_Francs( 50.00f),
   Twenty_Francs( 20.00f),
      Ten_Francs( 10.00f),
     Five_Francs(  5.00f),
      Teo_Francs(  2.00f),
       One_Franc(  1.00f),
     Fifty_Centimes(  0.50f),
    Twenty_Centimes(  0.20f),
       Ten_Centimes(  0.10f),
      Five_Centimes(  0.05f),
       Two_Centimes(  0.02f),
       One_Centime(  0.01f);
 
     private final float value;
     private final String description;
 
     bill(float value) {
         this.value = value;
         this.description = " " + this.name().replace("_", " ");
     }
 
     public float getValue() {
         return this.value;
     }
 
     @Override
     public String toString() {
         return this.description;
     }
 }

我的打印功能:


public static void getGhange(double price, double cash) {
    if (cash < price){
        System.out.println("Wrong buddy");
    } else if (cash == price) {
        System.out.println("Nothing");
    } else {  //CH > PP
        float remaining = (float) (cash - price);
        
        StringBuilder change = new StringBuilder();
        for (bill d : bill.values()) { 
            while (remaining >= d.getValue()) {
                remaining -= d.getValue();
                change.append(d).append(',');
            }
        }
        change.setLength(change.length() - 1); // remove , at the end
        System.out.println(change.toString().trim());
    }

}

4 个答案:

答案 0 :(得分:2)

我建议你把所有的东西都乘以 100,并且只处理整数。

这样可以避免比较时的浮点不精确。

或者,您可以使用任意精度类型。

第一个建议的实施:

public class ShifraSec {
    public static void main(String[] args) {
        getGhange(11.25, 20);
    }
    public enum bill {
        Fifty_Francs( 5000),
        Twenty_Francs( 2000),
        Ten_Francs( 1000),
        Five_Francs(  500),
        Two_Francs(  200),
        One_Franc(  100),
        Fifty_Centimes(  50),
        Twenty_Centimes(  20),
        Ten_Centimes(  10),
        Five_Centimes(  5),
        Two_Centimes(  2),
        One_Centime(  1);

        private final float value;
        private final String description;

        bill(float value) {
            this.value = value;
            this.description = " " + this.name().replace("_", " ");
        }

        public float getValue() {
            return this.value;
        }

        @Override
        public String toString() {
            return this.description;
        }
    }

    public static void getGhange(double price, double cash) {
        int intPrice = (int)(price * 100);
        int intCash = (int)(cash * 100);
        if (intCash < intPrice){
            System.out.println("Wrong buddy");
        } else if (intCash == intPrice) {
            System.out.println("Nothing");
        } else {  //CH > PP
            int remaining = (intCash - intPrice);

            StringBuilder change = new StringBuilder();
            for (bill d : bill.values()) {
                while (remaining >= d.getValue()) {
                    remaining -= d.getValue();
                    change.append(d).append(',');
                }
            }
            change.setLength(change.length() - 1); // remove , at the end
            System.out.println(change.toString().trim());
        }

    }

}

这是输出(我冒昧地将 Teo 法郎更改为两法郎): “五法郎,两法郎,一法郎,五十生丁,二十生丁,五生丁”

答案 1 :(得分:1)

处理金钱时,您应该使用专用库,或BigDecimal

使用 BigDecimal 您必须更改代码:

public static void getGhange(BigDecimal price, BigDecimal cash) {
    if (cash.compareTo(price) < 0){
        System.out.println("Wrong buddy");
    } else if (cash.equals(price)) {
        System.out.println("Nothing");
    } else {  //CH > PP
        BigDecimal remaining = cash.subtract(price);

        StringBuilder change = new StringBuilder();
        for (bill d : bill.values()) {
            while (remaining.compareTo(d.getValue()) >= 0) {
                remaining = remaining.subtract(d.getValue(), new MathContext(2));
                change.append(d).append(',');
            }
        }
        change.setLength(change.length() - 1); // remove , at the end
        System.out.println(change.toString().trim());
    }

}

但现在它返回 Five Centimes 而不是 Two Centimes, Two Centimes, One Centime,所以如果你需要 Five Centimes 你必须修改算法(但现在它可以按预期使用货币,浮点精度没有任何问题)

他的示例精度设置为 2 位数字 remaining.subtract(d.getValue(), new MathContext(2));

并且您的枚举方法返回值应该返回 BigDecimal

public BigDecimal getValue() {
    return BigDecimal.valueOf(this.value);
}

答案 2 :(得分:0)

好的,我能够解决它,发现在 while 循环中使用 Math.round() 可以轻松解决它:

这一行:

remaining -= d.getValue();

变成这样:

remaining -= Math.round(d.getValue()*100) / 100.0

我使用的重要资源: https://java2blog.com/java-round-double-float-to-2-decimal-places/

答案 3 :(得分:0)

只需按照贡献者在上面给出的内容进行以下更改。

public static void getChange(double price, double cash) {
        if (cash < price) {
            System.out.println("Wrong buddy");
        } else if (cash == price) {
            System.out.println("Nothing");
        } else { // CH > PP
            float remaining = (float) (cash - price);

            StringBuilder change = new StringBuilder();
            for (bill d : bill.values()) {
                while (remaining >= d.getValue()) {
                    remaining -= Math.round(d.getValue()*100.0)/100.0;
                    change.append(d).append(',');
                }
            }
            change.setLength(change.length() - 1); // remove , at the end
            System.out.println(change.toString().trim());
        }

    }

它会按预期结果,仍然使用其他可以使其更简单的方法。