5

I already have several ways to solve this, but I am interested in whether there is a better solution to this problem. Please only respond with a pure numeric algorithm. String manipulation is not acceptable. I am looking for an elegant and efficient solution.

Given a currency value (ie $251.03), split the value into two half and round to two decimal places. The key is that the first half should round up and the second should round down. So the outcome in this scenario should be $125.52 and $125.51.

kakridge
  • 2,153
  • 1
  • 17
  • 27
  • 1
    Stack overflow whould be a more apropriate site – Tom Squires Jul 01 '11 at 14:14
  • I have removed the language specific comments. This is an algorithm question. – kakridge Jul 01 '11 at 14:29
  • When you say pure numeric algorithm are things like the round function acceptable? If not what about MOD and ABS? Can I abuse datatypes? – Jon Hopkins Jul 01 '11 at 14:45
  • Yes, round, mod, abs, are fine. Anything that would typically be in a math library. – kakridge Jul 01 '11 at 14:49
  • You should not use (binary) floating point numbers to represent decimal monetary values - it will get wrong. Use either integers (as cents), or some decimal number type (depending on your language/library). Then the rounding gets easy. – Paŭlo Ebermann Jul 01 '11 at 18:22

4 Answers4

5

Divide by two, round to 2 d.p. (in C# this is decimal.Round(value, 2)), subtract the rounded value from the original, and sort them using an if. Your library may support control over the rounding which can save you the if - with C# you can do this using the 3-parameter overload of decimal.Round.

Peter Taylor
  • 4,918
  • 1
  • 34
  • 59
1
money = amount_you_are_dividing
bigmoney = ceiling((money / 2) * 100)/100
littlemoney = money - bigmoney

This of course assumes you have access to a math library with a ceiling function.

0

Some php logic to round currency values to a specified amount. (Penny, nickel, dime, quarter, 50c, dollar.)

The calling statement passes the original value as the first argument, and the rounding unit (.05, .10, .25, .50, 1.00) as the second.

e.g.

$price = invtround{$value, .10} ;

The function returns the rounded value.

function invtround($x,$y)
{
 if ($x == 0.01) {

  $result = $y ;
 }


 if ($x == .05) {

  $floor = round($y,1) ;
  if ($floor > $y) {$floor = $floor - $x ;}
  $diff  = $y - $floor ;
  if ($diff < .03) {$result = $floor ;}  
  else if ($diff < .08) {$result = $floor + .05;} 
  else {$result = $floor + .10;} 
 }

 if ($x == .10) {

  $floor = round(floor($y*10)/10,1) ;
  if ($floor > $y) {$floor = $floor - $x ;}
  $diff  = $y - $floor ;
  if ($diff < .05) {$result = $floor ;}  
  else {$result = $floor + .10;}
 }

 if ($x == .25) {
  $floor = floor($y*10)/10 ;
  $diff  = $y - $floor ;
  if ($diff < .13) {$result = $floor ;}
  else if ($diff < .38) {$result = $floor +.25;}  
  else if ($diff < .68) {$result = $floor + .50;}  
  else if ($diff < .88) {$result = $floor + .75;}  
  else {$result = $floor + 1.0;}
 }

 if ($x == .50) {
  $floor = floor($y*10)/10 ;
  $diff  = $y - $floor ;
  if ($diff < .25) {$result = $floor ;}
  else if ($diff < .75) {$result = $floor + .50;}  
  else {$result = $floor + 1.0;}
 }
 if ($x == 1.00){$result = round($y,0) ;}
 $result = number_format($result,2);
 return $result ;
}
j0k
  • 22,600
  • 28
  • 79
  • 90
RGS
  • 1
0

I assume that you are representing your currency using integers (and not floating-point), so that the currency value ¤123.45 is represented by the integer v = 12345.

Then the larger portion is (v + 1) / 2 and the smaller portion is v / 2.

(If you are using floating-point numbers to represent currency, see this question.)

Community
  • 1
  • 1
Gareth Rees
  • 64,967
  • 9
  • 133
  • 163