货币 - 圆形双值只有在十进制位置以上以上时



我正在尝试拆分账单,并且需要计算如果票据分均匀分配,则每个人将欠多少账单。我知道一个数量与其他损失的美分不同。

假设3个人试图将200/3的账单分配。200/3是66.6666666667。我计划做的是向2个人收取66.67的费用,最后一个账单很幸运。

到目前为止,我有一个:

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中?

也许我以错误的方式接近这一点。我知道货币可能很挑剔。

甚至在考虑算术之前,您需要知道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%,因此更好的解决方案是通过减去误差(或添加错误为负(,从第一个(或最后一个或随机选择(均匀分布(或添加错误((errorCents食客。

然后,其余的解决方案是关于延长上述内容的,我将其留给读者。

作为附带说明,使用Cents是银行传输金额的方式(至少对于EFTPOS(。


关于基本软件设计,我将创建一个单独的方法,该方法接受整数美分,人们算作其参数,并返回"拆分"量的数组。这样做不仅可以使您的代码更容易阅读,而且会使算术操作区分开,从而使许多简单的测试更容易编写,这样您就可以知道自己拥有所有可以想到的边缘案例。<<<<<<<<<<<</p>

您可以使用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();
    }

您只能使用基本原始图来完成所有计算额外的SDK/数学操纵。以下是使用以下建议完全解决此问题的工作示例:

public class AmountDivider {
    private int totalMembers, luckies, unluckies;
    private double totalAmount, amountPerLucky, amountPerUnlucky;
    
    public AmountDivider(int numMembers, double amountOwed) {
        totalMembers = numMembers;
        totalAmount = amountOwed;
        double centsOwed = amountOwed * 100;
        int centsPerMember = (int)(centsOwed / totalMembers);
        int centsLeft = (int)centsOwed - centsPerMember * totalMembers;
        
        luckies = totalMembers - centsLeft;
        amountPerLucky = centsPerMember / 100.0;
        unluckies = centsLeft;
        amountPerUnlucky = (centsPerMember + 1) / 100.0;
    }
    public String toString() {
        String luckiesStr = String.format("%d lucky persons will pay %.2f", luckies, amountPerLucky);
        String unluckiesStr = String.format("%d unlucky persons will pay %.2f", unluckies, amountPerUnlucky);
        return String.format("For amount %f divided among %d: n%sn%sn", 
                                totalAmount, totalMembers, luckiesStr, unluckiesStr);
    }
    
    public static void main(String[] args) {
        System.out.println(new AmountDivider(3, 200));
        System.out.println(new AmountDivider(17, 365.99));
    }
}

github上的完整代码

希望这会有所帮助。

最新更新