货币-仅在小数点后2位以上的情况下才舍入double值

时间:2019-05-14 22:16:16

标签: java rounding

我正在尝试拆分账单,需要计算如果账单按均等金额拆分时每个人的欠款。我知道其中一个会与其余的有所不同,以弥补损失的美分。

假设3个人尝试将帐单拆分为200。200/ 3为66.6666666667。我打算做的是向前两个人收取66.67的费用,而最后一个人因66.66的账单而幸运。

目前为止,我有以下内容:

private String calculateAmountToPay(String noOfParticipants, String owed) {
    double amountOwed = Double.parseDouble(owed);
    int noOfMembers = Integer.parseInt(noOfParticipants);
    DecimalFormat amountFormat = new DecimalFormat("#.##");
    amountFormat.setRoundingMode(RoundingMode.CEILING);
    return amountFormat.format((amountOwed/(double)noOfMembers) / 100);
  }

但这总是返回66.67。有没有一种方法可以让我仅在数字大于小数点后两位的情况下才将其四舍五入,如果没有,则保持在例如66.66?

也许我正在以错误的方式来对待。我知道货币可能难以应付。

3 个答案:

答案 0 :(得分:2)

在考虑算术之前,您需要知道double 不是适合用于货币的数据类型,因为它不精确。因此,停止使用浮点类型(例如double)作为美元数量的数据类型,并开始使用精确类型(例如long)作为数据类型 cents 的数量。

然后进行计算的步骤将是立即将所有内容四舍五入为美分:

double amountOwed = ...;
int noOfMembers = ...;
long centsOwed = Math.round(amountOwed * 100);
long portionCents = Math.round(amountOwed * 100 / noOfMembers);
long errorCents = portionCents * noOfMembers - centsOwed;

这是处理错误的一种方法:

long lastPortionCents = portionCents - errorCents;

但是误差有可能超过1美分,因此更好的解决方案是通过从第一个(或最后一个或随机选择的)中减去(或在误差为负数时加上)1美分来平均分配误差)errorCents用餐者。

剩下的解决方案是将上面的内容,我留给读者。

请注意,使用美分是银行传输金额的方式(至少对于EFTPOS而言)。


关于基本软件设计,我将创建一个单独的方法,该方法接受整数美分,并且人计数作为其参数,并返回“分割”金额的数组。这样做不仅会使您的代码更易于阅读,而且会分隔算术运算,从而使许多简单的测试更容易编写,因此您可以知道所有可以想到的边缘情况。 / p>

答案 1 :(得分:0)

您可以在半舍入模式下使用BigDecimal:

    private String calculateAmountToPay(String noOfParticipants, String owed) {
        double amountOwed = Double.parseDouble(owed);
        int noOfMembers = Integer.parseInt(noOfParticipants);
        BigDecimal amount= new BigDecimal((amountOwed / (double) noOfMembers) / 100);
        return amount.setScale(2, RoundingMode.HALF_UP).toString();
    }

答案 2 :(得分:0)

您可以使用基本原语进行所有计算,将所有内容转换为美分(2位小数精度),然后将剩余的美分除以一部分成员,而无需使用额外的sdks / math运算来使其过于复杂。以下是使用这些建议完全解决此问题的可行示例:

$('.modal').click(function(event){
    $(event.target).modal('hide');
});

希望这会有所帮助。