【问题标题】:Cash Register Computation problems | Java收银机计算问题 |爪哇
【发布时间】:2021-02-09 19:00:37
【问题描述】:

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

0.04 和 0.02 我猜是问题所在!


我的问题:

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

  • 一法郎:0.01
  • 两法郎:0.02
  • 五法郎:0.05
  • 十法郎:0.10
  • 二十法郎:.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 of 2 centtimes 而不是 5 centtimes 所以我矮了 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());
    }

}

【问题讨论】:

标签: java logic project


【解决方案1】:

我建议您将所有内容都乘以 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 Francs 更改为 2 Francs): '五法郎,两法郎,一法郎,五十生丁,二十生丁,五生丁'

【讨论】:

  • 我正在尝试使用 DecimalFormat 但遇到问题
  • DecimalFormat 用于格式化目的,它不会修复不精确性。尝试按照@BoyFarmer 的建议使用 BigDecimal 或使用整数(最低单位为 1 厘米)。
  • 是的,我尝试使用 Formater 没有用,谢谢并赞成告诉我为什么:) 我认为它可以根据我的喜好格式化实际数据 - 其中 python 有类似的东西。
【解决方案2】:

在使用金钱时,您应该使用专用库,或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());
    }

}

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

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

你的枚举方法返回值应该返回BigDecimal

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

【讨论】:

  • 是的,我也在考虑 BigDeciml,但我不明白它们是如何完全工作的,所以我恢复到使用 Math.round() 的更简单方法“当使用金钱时,你应该使用专用库“确实赞成该建议,即您应该始终做的事情。但是,在我个人的情况下,我不想......这是为了让我对 java 重新思考,因为我很长时间没有使用它,因此我只想使用核心 java
【解决方案3】:

好的,我能够解决它发现在 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/

【讨论】:

    【解决方案4】:

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

    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());
            }
    
        }
    

    它会如预期的那样产生结果,但仍在使用其他可能使其更简单的方法。

    【讨论】:

    • 用“if”代替“while”会导致必须复制账单的错误。例如,假设价格 = 11.24 和现金 = 20。最后两张钞票应该是“两生钱,两生钱”,但使用 if 只会通过两生钱一次。
    • 您好 Eduardothanx 您的评论,我发现了错误。我已经更正了我上面的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-17
    • 2012-07-23
    相关资源
    最近更新 更多