【问题标题】:How to display correct amount of change?如何显示正确的变化量?
【发布时间】:2019-09-07 22:52:38
【问题描述】:

我对 Java 很陌生,正在尝试创建一个简单的程序,将大量金钱转换为零钱。但是,我发现该程序总是比必要的少打印一分钱。

我会在打印之前将 1 添加到我的 pennies 变量中,但这意味着当零钱为 0 时,它仍会添加一美分作为零钱。

这是我的代码:

change = amtPaid-Math.round((total*1.13)*100)/100.0;
pennies = (int) (change * 100);
twenties = (int)(pennies/2000);
        pennies %= 2000;
tens = (int)(pennies/1000);
        pennies %= 1000;
fives = (int)(pennies/500);
        pennies %= 500;
toonies = (int)(pennies/200);
        pennies %= 200;
loonies = (int)(pennies/100);
        pennies %= 100;
quarters = (int)(pennies/25);
        pennies %= 25;
dimes = (int)(pennies/10);
        pennies %= 10;
nickels = (int)(pennies/5);
        pennies %= 5;

我在提供示例输入后得到这个输出:

The change will be:  1.83

To make up this amount, you will need:
      0  twenty-dollar bills      0  ten-dollar bills
      0  five-dollar bills        0  toonies
      1  loonies                  3  quarters
      0  dimes                    1  nickels
      2  pennies

有谁知道为什么会发生这种情况以及如何解决?

【问题讨论】:

  • 第一次计算时显示便士,检查是否存在某种舍入误差!?
  • 大概和这个amtPaid-Math.round((total*1.13)*100)/100.0;有关
  • 我已经删除了你的concurrency,因为我看不出这个问题与这个主题/多线程有什么关系。
  • 在您第一次为其赋值后立即打印pennies 的值。它实际上打印为183吗?
  • 别担心……加拿大没有一分钱。然而,有 Loonies 和 Toonies。

标签: java rounding


【解决方案1】:

在我看来,将您的总计(成本和税金全部计算在内)精确到不超过 2(即:55.28)的小数精度。 不允许小数精度超过 2。无论您使用哪种舍入机制,请确保您对最终结果感到满意。

已付金额中减去欠款,并确保最终结果精确到小数点2(即:60.00 - 55.2814 = 4.7186 = 4.72 {四舍五入})。如果不正确四舍五入到小数点精度 2,您在计算返回的零钱时可能会损失或获得一分钱。

返还金额分为美元美分。两者都应该是整数值(即:4 美元和 72 美分)。

// A value for the sake of this example. Taxes Included!
double totalOwed   = 52.26534;   
// Round to a precision of 2 (round UP on .5)
double grandTotal  = BigDecimal.valueOf(totalOwed)
                     .setScale(2, RoundingMode.HALF_UP).doubleValue();
// A value for the sake of this example.    
double amountPaid  = 60.00;    
// Round to a precision of 2 (round UP on .5)
double returnValue = BigDecimal.valueOf(amountPaid - grandTotal)
                     .setScale(2, RoundingMode.HALF_UP).doubleValue();

int dollars = Integer.parseInt(String.valueOf(returnValue).split("\\.")[0]);
int cents   = Integer.parseInt(String.valueOf(returnValue).split("\\.")[1]);

计算出要退回的票据货币并将其添加到列表中以供稍后显示。有很多不同的方法可以做到这一点。这是一种方法:

List<String> change = new ArrayList<>();
int returnVal;

// Some displayable information
change.add("Total Cost:    --> " + String.valueOf(grandTotal));
change.add("Total Paid:    --> " + String.valueOf(amountPaid));
change.add("Return change: --> " + String.valueOf(returnValue));

// 100 Dollar Bills 
if (dollars >= 100) {
    returnVal = dollars / 100;
    change.add("  " + String.valueOf(returnVal) + " Hundred Dollar Bill(s)");
    dollars -= (returnVal * 100);
}
// 50 Dollar Bills 
if (dollars >= 50) {
    returnVal = dollars / 50;
    change.add("  " + String.valueOf(returnVal) + " Fifty Dollar Bill(s)");
    dollars -= (returnVal * 50);
}
// 20 Dollar Bills 
if (dollars >= 20) {
    returnVal = dollars / 20;
    change.add("  " + String.valueOf(returnVal) + " Twenty Dollar Bill(s)");
    dollars -= (returnVal * 20);
}
// 10 Dollar Bills 
if (dollars >= 10) {
    returnVal = dollars / 10;
    change.add("  " + String.valueOf(returnVal) + " Ten Dollar Bill(s)");
    dollars -= (returnVal * 10);
}
// 5 Dollar Bills 
if (dollars >= 5) {
    returnVal = dollars / 5;
    change.add("  " + String.valueOf(returnVal) + " Five Dollar Bill(s)");
    dollars -= (returnVal * 5);
}
// 2 Dollar Bills 
if (dollars >= 2) {
    returnVal = dollars / 2;
    change.add("  " + String.valueOf(returnVal) + " Two Dollar Bill(s)");
    dollars -= (returnVal * 2);
}
// 1 Dollar Bills 
if (dollars >= 1) {
    returnVal = dollars / 1;
    change.add("  " + String.valueOf(returnVal) + " One Dollar Bill(s)");
    dollars -= (returnVal * 1);
}

// Quarters (working against cents now)
if (cents >= 25) {
    returnVal = cents / 25;
    change.add("  " + String.valueOf(returnVal) + " Quarter(s)");
    cents -= (returnVal * 25);
}
// Dimes
if (cents >= 10) {
    returnVal = cents / 10;
    change.add("  " + String.valueOf(returnVal) + " Dime(s)");
    cents -= (returnVal * 10);
}
// Nickles
if (cents >= 5) {
    returnVal = cents / 5;
    change.add("  " + String.valueOf(returnVal) + " Nickle(s)");
    cents -= (returnVal * 5);
}
// Pennies
if (cents >= 1) {
    returnVal = cents / 1;
    change.add("  " + String.valueOf(returnVal) + " Pennies");
    cents -= (returnVal * 1);
}

// Display the Change-Back in Console Window
for (String str : change) {
    System.out.println(str);
}

如您所见,上面的示例中有很多重复的代码。您可以通过另一种方式摆脱这种情况。您可以利用数组或集合机制来保存美元和硬币面额,例如:

// A value for the sake of this example. Taxes Included!
double totalOwed   = 52.26534;   
// Round to a precision of 2 (round UP on .5)
double grandTotal  = BigDecimal.valueOf(totalOwed)
                     .setScale(2, RoundingMode.HALF_UP).doubleValue();
// A value for the sake of this example.    
double amountPaid  = 60.00;    
// Round to a precision of 2 (round UP on .5)
double returnValue = BigDecimal.valueOf(amountPaid - grandTotal)
                     .setScale(2, RoundingMode.HALF_UP).doubleValue();

int dollars = Integer.parseInt(String.valueOf(returnValue).split("\\.")[0]);
int cents   = Integer.parseInt(String.valueOf(returnValue).split("\\.")[1]);

List<String> change = new ArrayList<>();
int returnVal;

// Using arrays (or a collection mechanism) like this 
// allows you to set whatever denominations you like.
String[][] dollarDenominations = {
    {"100", " Hundred Dollar Bill(s)"},
    {"50" , " Fifty Dollar Bill(s)"  },
    {"20" , " Twenty Dollar Bill(s)" },
    {"10" , " Ten Dollar Bill(s)"    },
    {"5"  , " Five Dollar Bill(s)"   },
    {"2"  , " Two Dollar Bill(s)"    },
    {"1"  , " One Dollar Bill(s)"    }
};

// Although not commonly used, you might even want to
// add 50 cent pieces to the Array.
String[][] coinDenominations = {
    {"25", " Quarter(s)"},
    {"10", " Dime(s)"   },
    {"5" , " Nickle(s)" },
    {"1" , " Pennies"   }
};

// Some displayable information
change.add("Total Cost:    --> " + String.valueOf(grandTotal));
change.add("Total Paid:    --> " + String.valueOf(amountPaid));
change.add("Return change: --> " + String.valueOf(returnValue));

// Dollar Denominations
for (int i = 0; i < dollarDenominations.length; i++) {
    int denom = Integer.parseInt(dollarDenominations[i][0]);
    String typeString = dollarDenominations[i][1];
    if (dollars >= denom) {
        returnVal = dollars / denom;
        change.add("  " + String.valueOf(returnVal) + typeString);
        dollars -= (returnVal * denom);
    }
}

// Coin Denominations
for (int i = 0; i < coinDenominations.length; i++) {
    int denom = Integer.parseInt(coinDenominations[i][0]);
    String typeString = coinDenominations[i][1];
    if (cents >= denom) {
        returnVal = cents / denom;
        change.add("  " + String.valueOf(returnVal) + typeString);
        cents -= (returnVal * denom);
    }
}

// Display the Change-Back data in Console Window...
for (String str : change) {
    System.out.println(str);
}

如前所述,还有其他几种方法可以做这种事情。重要的是针对小数点后 2 位的 Change-Back 值进行处理。毕竟……据我所知,没有六分之一便士这样的面额(@9​​87654321@ 没有面额)。美国曾经(1793 年至 1857 年间)曾经有一个 半便士,但由于显而易见的原因,它已不复存在并且永远不会再存在。在加拿大没有一分钱,因为制作一个几乎要花费 2 美分,最终(在我看来)美国很可能会遵循这一计划,并在此过程中节省数百万美元,因为它的成本也约为。 1.82+ 美分赚一美分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2021-02-09
    • 1970-01-01
    • 2021-07-01
    相关资源
    最近更新 更多