【问题标题】:Why does it keep rounding down to two cents on my java change/cashier program?为什么在我的 java 零钱/收银员程序中它总是四舍五入到 2 美分?
【发布时间】:2014-02-07 14:56:31
【问题描述】:

我尝试了很多方法,例如 math.Round 并让它们成为双精度数和整数,但我不知道为什么以及在哪里最后四舍五入到 2 美分。当我购买 32.27 并用 36 支付时,答案是 3 美元 2 季度 2 毛钱 2 美分。 这是我的代码:

import java.util.Scanner;

public class Change {

    public static void main(String[] args) {

        Scanner input = new Scanner(System.in);


        System.out.print("Purchase: ");
        double purchase = input.nextDouble();
        System.out.print("Payment: ");
        double amountGiven = input.nextDouble();

        int remainingAmount = (int) ((amountGiven - purchase) * 100);


        int numOfDollars = remainingAmount / 100;
        remainingAmount = remainingAmount % 100;

        int numOfQuarters = remainingAmount / 25;
        remainingAmount = remainingAmount % 25;

        int numOfDimes = remainingAmount / 10;
        remainingAmount = remainingAmount % 10;

        int numOfPennies = remainingAmount;

        System.out.println("Given $ " + amountGiven + " for a purchase of $ " +
                purchase + " we need " + numOfDollars + " dollars " + numOfQuarters +
                " quarters " + numOfDimes + " dimes " +
                numOfPennies + " cents ");
    }
}

【问题讨论】:

标签: java rounding


【解决方案1】:

如果你运行这段代码,你会发现问题出在哪里:

final double purchase = 32.27;
System.out.println("Purchase: " + new BigDecimal(purchase));
final double diff = 36 - purchase;
System.out.println("Difference: " + new BigDecimal(diff));
System.out.println("Cent difference: " + (int)(100*diff));

输出将是

Purchase: 32.27000000000000312638803734444081783294677734375
Difference: 3.72999999999999687361196265555918216705322265625
Cent difference: 372

因此您可以看到您的麻烦从一开始就开始了:十进制值 32.27 由最接近的 double 值表示,略大。然后差异略小,截断后下降一分。

教训:不要将输入解析为double,而是into a BigDecimal

【讨论】:

    【解决方案2】:

    发生这种情况是因为金额不能精确地表示为双精度数。当您转换为 int 时,它会被截断。

    如果用 14 位小数打印,则以美分为单位的找零金额为 372.99999999999955。

    使用BigDecimal 或仅使用Integerint 进行计算的自定义Currency 类型。

    【讨论】:

    • 我还在学习如何编码,所以我不知道 BigDecimal。如何在代码中实现 BigDecimal?
    • 你不知道它是标准库的一部分,做适量的研究
    【解决方案3】:

    这种类型的计算应该从不使用原始类型。始终使用BigDecimal

    【讨论】:

    • 也可以使用intlong 来表示美分数。
    • 不是真的,如果您打算支持多种货币,或者用逗号后几个数字衡量的东西,比如汇率等等。
    【解决方案4】:

    你不能在不损失精度的情况下对整数类型进行除法运算

    double d1 = 32.27;
    double d2 = 36;
    int i1 = (int) (d1 * 100);
    int i2 = (int) (d2 * 100);
    int rad = (int) ((d1 - d2 ) * 100);
    int rai = i1 - i2;
    double rdd = (double)rai / 100; // <- this is what you are expecting
    int ndi = rai / 100;            
    //  ^ this is what you are getting 
    //  int / int == double which gets silently truncated
    
    System.out.println("i1 = " + i1);
    System.out.println("i2 = " + i2);
    System.out.println("rad = " + rad);
    System.out.println("rai = " + rai);
    System.out.println("rdd = " + rdd); // mostly accurate in this case
    System.out.println("ndi = " + ndi); // truncated
    

    输出

    i1 = 3227
    i2 = 3600
    rad = -372
    rai = -373
    rdd = -3.73
    ndi = -3
    

    【讨论】:

    • 实际上,我认为整数除法是这里的预期操作(并且按预期工作)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多