I am trying to work on a program for work with multiple BigDecimal calculations necessary. I am at quite a confusing point because the BigDecimal is not cooperating how I would like. Let me explain what I need it to do:
First it takes a monetary amount which can have up to two decimal places. Then it takes the "allocations" which is basically how many accounts that amount will be spread up through.
The program should now divide the amount between the accounts. Of course in some situations the amount can not be evenly divided, for example $3.33 divided between 2 accounts. In that case you must either have 1 allocation with a extra cent or round the number. Rounding is not an option, every penny must be accounted for. Here is what I have so far:
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);
Later in the class I actually write the values. I have a counter first that is set as the totalAllocations. I then have a loop that will write a bit of information including the dividedAllocationAmount. So say the amountTotal had been 10 and I had two allocations then 5.00 would be written twice.
What I want is for situations where the total can't be evenly divided among the allocations for there to be one extra allocation to hold the remainder as shown below:
if(remainderAllocation.compareTo(BigDecimal.ZERO) >0 && allocationCounter==1){
adjAmt.setValue(remainderAllocation);
}else{
adjAmt.setValue(dividedAllocationAmount);
}
The adjAmt is just setting an XML field, this is a JAXB project.
The main issue I have here is with numbers with a remainder. For example if a user selects 2 allocations and the amount is $3.33 then the program will fail and give me a rounding error.
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
The same happens if the total amount is $10.51 and there are 3 allocations. In reality what I want is for two allocations to be for $5.25 and the 3rd allocation to be for $0.01. (Since that is the remainder). What do I do?