首页 文章

BigDecimal除以小数位数不均匀

提问于
浏览
0

我正在尝试使用必要的多个BigDecimal计算工作的程序 . 我处于一个令人困惑的地步,因为BigDecimal没有合作我想要的 . 让我解释一下我需要它做什么:

首先,它需要一个货币金额,最多可以有两位小数 . 然后它需要“分配”,这基本上是多少帐户将分配金额 .

该程序现在应该在帐户之间划分金额 . 当然,在某些情况下,金额不能平均分配,例如$ 3.33除以2个账户 . 在这种情况下,您必须要么有1分配额外的分数或围绕数字 . 舍入不是一种选择,必须考虑每一分钱 . 这是我到目前为止:

totalAllocations = TransactionWizard.totalAllocations;//Set in another class, how many accounts total will be spread

    BigDecimal totalAllocationsBD = new BigDecimal(totalAllocations).setScale(2);//Converts to big decimal. 

    amountTotal = (BigDecimal) transInfo.get("amount"); // set total amount

    MathContext mc = new MathContext(2);
    remainderAllocation = amountTotal.remainder(totalAllocationsBD, mc);

    dividedAllocationAmount = amountTotal.divide(totalAllocationsBD, MathContext.DECIMAL32);

    dividedAllocationAmount=dividedAllocationAmount.setScale(2);

在课程的后面,我实际上写了值 . 我首先将一个计数器设置为totalAllocations . 然后我有一个循环,它将写入一些信息,包括divideAllocationAmount . 所以说amountTotal是10,我有两个分配然后5.00会被写两次 .

我想要的是总数不能在分配中平均分配的情况,以便有一个额外的分配来保存余数,如下所示:

if(remainderAllocation.compareTo(BigDecimal.ZERO) >0 && allocationCounter==1){
                adjAmt.setValue(remainderAllocation);
            }else{
                adjAmt.setValue(dividedAllocationAmount);
            }

adjAmt只是设置一个XML字段,这是一个JAXB项目 .

我在这里遇到的主要问题是带有余数的数字 . 例如,如果用户选择2个分配且金额为3.33美元,则程序将失败并给出舍入错误 .

Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException: Rounding necessary
    at java.math.BigDecimal.commonNeedIncrement(Unknown Source)
    at java.math.BigDecimal.needIncrement(Unknown Source)
    at java.math.BigDecimal.divideAndRound(Unknown Source)
    at java.math.BigDecimal.setScale(Unknown Source)
    at java.math.BigDecimal.setScale(Unknown Source)
    at model.Creator.createTransaction(Creator.java:341)
    at view.TransactionWizard$2.actionPerformed(TransactionWizard.java:333)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.WaitDispatchSupport$2.run(Unknown Source)
    at java.awt.WaitDispatchSupport$4.run(Unknown Source)
    at java.awt.WaitDispatchSupport$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.awt.WaitDispatchSupport.enter(Unknown Source)
    at java.awt.Dialog.show(Unknown Source)
    at java.awt.Component.show(Unknown Source)
    at java.awt.Component.setVisible(Unknown Source)
    at java.awt.Window.setVisible(Unknown Source)
    at java.awt.Dialog.setVisible(Unknown Source)
    at view.MainView$15$1.run(MainView.java:398)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
Local Instrument: WEB

如果总金额为10.51美元并且有3个分配,则会发生同样的情况 . 实际上我想要的是两个分配为5.25美元,第三个分配为0.01美元 . (因为那是剩下的) . 我该怎么办?

2 回答

  • 2

    当然,在某些情况下,金额不能平均分配,例如$ 3.33除以2个账户 . 在这种情况下,您必须要么有1分配额外的分数或围绕数字

    [没有优化,最佳实践,错误处理,数据类型转换等普通工作伪代码 . ]

    试试这个

    float amount = 3.33f;
    
            int allocations = 2;
    
            double average = amount/allocations;
    
            System.out.println("ACTUAL AVERAGE "+average);
    
            double rounded = Math.round(average * 100.0) / 100.0;
    
            System.out.println("ROUNDED VALUE: "+rounded);
    
            double adjustment = average - rounded;
    
            adjustment*=allocations; //-- FOR EACH ALLOCATION
    
            for(int i=1; i<allocations; i++){
                System.out.println("Allocation :" +i + " = "+rounded);
            }
    
            //-- ADDING ADJUSTED ROUNDING AMOUNT TO LAST ONE
            double adjustedAmount = Math.round((rounded+adjustment) * 100.0) / 100.0;
    
            System.out.println("Allocation :" +allocations +" = " + adjustedAmount);
    

    输出金额3.33,分配2次 .

    ACTUAL AVERAGE 1.6649999618530273
    ROUNDED VALUE: 1.66
    Allocation :1 = 1.66
    Allocation :2 = 1.67 //-- EXTRA CENT
    

    如果总金额为10.51美元并且有3个分配,则会发生同样的情况 . 实际上我想要的是两个分配为5.25美元,第三个分配为0.01美元 . (因为那是剩下的) . 我该怎么办?

    现在这与上面说的不同,你可以有3.5,3.5和3.51 .

    但是如果你想单独使用0.01,那么改变上面的代码分配-1并将余数设置为最后一次分配 . 因此,对于第3次分配,它将是5.25,2和余数0.01,希望这有所帮助 .

  • 0

    我终于通过自己的试验和错误找到了解决这个问题的方法 . 事实证明,对我而言,关键在于取出其余部分,然后进行分割 .

    因为我知道我想根据情况自动将大十进制分成三个部分,我这样做了..

    package mathtest;
    
    import java.math.BigDecimal;
    import java.math.MathContext;
    import java.math.RoundingMode;
    
    public class MathTest 
    
    {
    
        public static BigDecimal totalAmount;
        public static BigDecimal totalAllocations; 
        public static BigDecimal divisibleAmount;
        public static BigDecimal remainderAmount;
        public static BigDecimal subtractDecimal;
    
    
        public static void main(String args[]){
    
            MathContext mc = new MathContext(2);
    
            totalAmount = new BigDecimal(10.00).setScale(2,RoundingMode.HALF_UP);//Sets the total monetary amount. Standard monetary rounding. 
            totalAllocations = new BigDecimal(2);//The number of accounts the total amount will be split between. 
            subtractDecimal = new BigDecimal(1.00);//Used to remove one from the total allocations (to account for the remainder). 
    
            remainderAmount = totalAmount.remainder(totalAllocations, mc);//Gets the remainder assuming you tried to divide total/allocations. 
    
            totalAmount=totalAmount.subtract(remainderAmount);//Subtracts the remainder from the total. 
    
    
            if(remainderAmount.compareTo(BigDecimal.ZERO) >0){//If there is a remainder. 
    
            //The divisible amount is the total amount divided by the total allocations minus 1 (to account for remainder). 
            divisibleAmount=totalAmount.divide(totalAllocations.subtract(subtractDecimal));
    
            }else{//If there is no remainder 
    
                divisibleAmount=totalAmount.divide(totalAllocations);//The divisible amount is the total amount divided by the total allocations. 
            }
            if(remainderAmount.compareTo(BigDecimal.ZERO)>0){
            System.out.println(remainderAmount);    
            }
    
    
            //The below would be printed once for each allocation. 
    
            System.out.println(divisibleAmount);
        }
    
    }
    

相关问题