Thursday 15 January 2015

algorithm - accurate single pass penny computation -


We have a cost which should be assigned to the departments 1.nn another calculation to produce the share for each department It is 0 to 1 number with more than 5 decimal places. The sum of shares in all departments is exactly 1, but they are not necessarily equal.

The goal is to calculate the correct dollar and cents to bill each department. The sum of the bill must surely match the cost C, it can not be a few pennies or less, besides each Departmental stake should not require partial pennies. In addition, although this is not only appropriate to leave the rest on the final department, but it is not necessary to look back at the previous timeframe. Note that the shares of each department are almost always rounded up to the pan, almost always above / below some pennies.

Broadly the maximum example: C = 33.34, with each 4 department ok 0.2500 shares. Because 33.34 * 0.25 = 8.335 so you can see that the two departments have to pay 8.33 and the two have to pay 8.34. A correct assignment would be: D1 = 8.33, D2 = 8.34, D3 = 8.33, D4 = 8.34. If you score a goal, then every department pays 8.34, which results in an overage of $ 0.02. If you multiply it by several departments and many more costs, then you end up with a hundred dollar discrepancies.

I want to do it in close passage, that is, I do not want to do it through the loop. I am away from 0.02, then loop again and values ​​until it is not right. I want to do this in 1 pass. I would also like to know that this is the name of the algorithm.

In Perl:

  #! Use / usr / bin / perl strict; Use warnings; Use data: Dumper; Use list: AllUtils qw (sum); Print dumper allocation (10_000, .23, .37, .4); Print dumper allocation (33.34, .25, .25, .25, .25); Print dumper allocated (100, 1/3, 1/3, 1/3); Sub Allocation {My ($ C, @shares) = @_; My @alloc; While (my $ share = change @share) {push @alloc, sprintf '% .2f', $ C * $ share; $ C - $$ alloc [-1]; My $ denom = sum = shares; $ Shares for $ _ / = $ denom; } Return \ @alloc; }  

Output:

$ VAR1 = ['2300.00', '3700.00', '4000.00']; $ VAR1 = ['8.34', '8.33', '8.34', '8.33']; $ VAR1 = ['33.33 ', '33.33', '33.33 '];

No comments:

Post a Comment