I wrote a function to calculate the different coins I will received based on the amount enter. However, the function seem to be working for certain amount only.
Example when I enter $5.1, I should be have 5($1) and 1(1cent). But my function is returning me with 5($1), 1(5cent) and 4(1cent) instead.
I cant seem to figure out what is wrong with my function.
function coin_change($amount) {
$coinDenominations = array(
'1$' => 1.00,
'50c' => 0.50,
'20c' => 0.20,
'10c' => 0.10,
'5c' => 0.05,
'1c' => 0.01
);
$change = [];
foreach($coinDenominations as $denomiation => $value){
$count = floor($amount / $value);
$change[$denomiation] = $count;
if($amount > 0){
$amount -= ($count * $value);
}else{
return $change;
}
}
return $change;
}
echo "Enter amount: $amount <br/>";
var_dump(coin_change($amount));
CodePudding user response:
Your logic is fine. Your problem comes from limited precision of floating point numbers in the floor
function. When calculating floor(amount / $value)
, floor(0.99999999) will return 0.
You can fix that with round
. So your function would become:
function coin_change($amount) {
$coinDenominations = array(
'1$' => 1.00,
'50c' => 0.50,
'20c' => 0.20,
'10c' => 0.10,
'5c' => 0.05,
'1c' => 0.01
);
$change = [];
foreach ($coinDenominations as $denomination => $value) {
// Round will make sure that 0.99999 = 1
// Then floor(1) = 1
$count = floor(round($amount / $value, 2));
$change[$denomination] = $count;
$amount -= $count * $value;
$amount = round($amount, 2); // Fixes imprecision for operation above
if ($amount == 0.00) {
return $change;
}
}
return $change;
}
$amount = 5.1;
var_dump(coin_change($amount));