java - BigDecimal Dividing with uneven decimals -
i trying work on program work multiple bigdecimal calculations necessary. @ quite confusing point because bigdecimal not cooperating how like. let me explain need do:
first takes monetary amount can have 2 decimal places. takes "allocations" how many accounts amount spread through.
the program should divide amount between accounts. of course in situations amount can not evenly divided, example $3.33 divided between 2 accounts. in case must either have 1 allocation cent or round number. rounding not option, every penny must accounted for. here have far:
totalallocations = transactionwizard.totalallocations;//set in class, how many accounts total spread bigdecimal totalallocationsbd = new bigdecimal(totalallocations).setscale(2);//converts 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 class write values. have counter first set totalallocations. have loop write bit of information including dividedallocationamount. amounttotal had been 10 , had 2 allocations 5.00 written twice.
what want situations total can't evenly divided among allocations there 1 allocation hold remainder shown below:
if(remainderallocation.compareto(bigdecimal.zero) >0 && allocationcounter==1){ adjamt.setvalue(remainderallocation); }else{ adjamt.setvalue(dividedallocationamount); }
the adjamt setting xml field, jaxb project.
the main issue have here numbers remainder. example if user selects 2 allocations , amount $3.33 program fail , give me rounding error.
exception in thread "awt-eventqueue-0" java.lang.arithmeticexception: rounding necessary @ java.math.bigdecimal.commonneedincrement(unknown source) @ java.math.bigdecimal.needincrement(unknown source) @ java.math.bigdecimal.divideandround(unknown source) @ java.math.bigdecimal.setscale(unknown source) @ java.math.bigdecimal.setscale(unknown source) @ model.creator.createtransaction(creator.java:341) @ view.transactionwizard$2.actionperformed(transactionwizard.java:333) @ javax.swing.abstractbutton.fireactionperformed(unknown source) @ javax.swing.abstractbutton$handler.actionperformed(unknown source) @ javax.swing.defaultbuttonmodel.fireactionperformed(unknown source) @ javax.swing.defaultbuttonmodel.setpressed(unknown source) @ javax.swing.plaf.basic.basicbuttonlistener.mousereleased(unknown source) @ java.awt.component.processmouseevent(unknown source) @ javax.swing.jcomponent.processmouseevent(unknown source) @ java.awt.component.processevent(unknown source) @ java.awt.container.processevent(unknown source) @ java.awt.component.dispatcheventimpl(unknown source) @ java.awt.container.dispatcheventimpl(unknown source) @ java.awt.component.dispatchevent(unknown source) @ java.awt.lightweightdispatcher.retargetmouseevent(unknown source) @ java.awt.lightweightdispatcher.processmouseevent(unknown source) @ java.awt.lightweightdispatcher.dispatchevent(unknown source) @ java.awt.container.dispatcheventimpl(unknown source) @ java.awt.window.dispatcheventimpl(unknown source) @ java.awt.component.dispatchevent(unknown source) @ java.awt.eventqueue.dispatcheventimpl(unknown source) @ java.awt.eventqueue.access$500(unknown source) @ java.awt.eventqueue$3.run(unknown source) @ java.awt.eventqueue$3.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ java.security.protectiondomain$javasecurityaccessimpl.dointersectionprivilege(unknown source) @ java.security.protectiondomain$javasecurityaccessimpl.dointersectionprivilege(unknown source) @ java.awt.eventqueue$4.run(unknown source) @ java.awt.eventqueue$4.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ java.security.protectiondomain$javasecurityaccessimpl.dointersectionprivilege(unknown source) @ java.awt.eventqueue.dispatchevent(unknown source) @ java.awt.eventdispatchthread.pumponeeventforfilters(unknown source) @ java.awt.eventdispatchthread.pumpeventsforfilter(unknown source) @ java.awt.eventdispatchthread.pumpeventsforfilter(unknown source) @ java.awt.waitdispatchsupport$2.run(unknown source) @ java.awt.waitdispatchsupport$4.run(unknown source) @ java.awt.waitdispatchsupport$4.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ java.awt.waitdispatchsupport.enter(unknown source) @ java.awt.dialog.show(unknown source) @ java.awt.component.show(unknown source) @ java.awt.component.setvisible(unknown source) @ java.awt.window.setvisible(unknown source) @ java.awt.dialog.setvisible(unknown source) @ view.mainview$15$1.run(mainview.java:398) @ java.awt.event.invocationevent.dispatch(unknown source) @ java.awt.eventqueue.dispatcheventimpl(unknown source) @ java.awt.eventqueue.access$500(unknown source) @ java.awt.eventqueue$3.run(unknown source) @ java.awt.eventqueue$3.run(unknown source) @ java.security.accesscontroller.doprivileged(native method) @ java.security.protectiondomain$javasecurityaccessimpl.dointersectionprivilege(unknown source) @ java.awt.eventqueue.dispatchevent(unknown source) @ java.awt.eventdispatchthread.pumponeeventforfilters(unknown source) @ java.awt.eventdispatchthread.pumpeventsforfilter(unknown source) @ java.awt.eventdispatchthread.pumpeventsforhierarchy(unknown source) @ java.awt.eventdispatchthread.pumpevents(unknown source) @ java.awt.eventdispatchthread.pumpevents(unknown source) @ java.awt.eventdispatchthread.run(unknown source) local instrument: web
the same happens if total amount $10.51 , there 3 allocations. in reality want 2 allocations $5.25 , 3rd allocation $0.01. (since remainder). do?
of course in situations amount can not evenly divided, example $3.33 divided between 2 accounts. in case must either have 1 allocation cent or round number
[no optimization, best practices, error handling, data type conversion etc. plain working pseudo code.]
try this
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; //-- each allocation for(int i=1; i<allocations; i++){ system.out.println("allocation :" +i + " = "+rounded); } //-- adding adjusted rounding amount last 1 double adjustedamount = math.round((rounded+adjustment) * 100.0) / 100.0; system.out.println("allocation :" +allocations +" = " + adjustedamount);
output amount 3.33 2 allocations.
actual average 1.6649999618530273 rounded value: 1.66 allocation :1 = 1.66 allocation :2 = 1.67 //-- cent
the same happens if total amount $10.51 , there 3 allocations. in reality want 2 allocations $5.25 , 3rd allocation $0.01. (since remainder). do?
now different above said above, can have 3.5, 3.5 & 3.51.
but if want 0.01 separately, alter above code allocations-1 & set remainder last allocation. 5.25 2 & remainder 0.01 3rd allocation, hope helps.
Comments
Post a Comment