Hi,

I wrote some code to calculate how much change to give to a customer. Other than simply calculating the difference between the balance and the change tendered, the program also calculates how many of each bill and coin type to give. The program works well except for some cases where it short changes a customer by 1 penny. I have attached the code and two examples below (one with and the other without the rounding issue).

Any help to find out why the rounding error happens and/or suggest a better way to write the code would be appreciated.

Regards,
Amit

#!/usr/bin/perl

use strict;
use warnings;

my ($billAmt, $paidAmt, $change);

print "Enter the Bill Amount: ";
$billAmt = <STDIN>;
chomp($billAmt);

print "Enter the Paid Amount: ";
$paidAmt = <STDIN>;
chomp($paidAmt);

$change = $paidAmt - $billAmt;

my %changeDenom = (
	100 => "hundred dollar",
	 50 => "fifty dollar",
	 20 => "twenty dollar",
	 10 => "ten dollar",
	  5 => "five dollar",
	  1 => "one dollar",
   0.25 => "quarter",
   0.10 => "dime",
   0.05 => "nickel",
   0.01 => "penny",
);

print "Bill total is  : \$$billAmt\n";
print "Paid amount is : \$$paidAmt\n";
print "------------------------\n";
print "Change comes to: \$$change\n";

my $remainingChange = $change;
my $billCount = 0;
my %changeCount = ();

foreach ( sort {$b <=> $a} keys %changeDenom) {
	$billCount = int($remainingChange / $_);
	
	if ($billCount >= 1) {
		$changeCount{$_} = $billCount;
	}

	$remainingChange = &fracMod($remainingChange, $_); 		
}

my $hashKeyCount = scalar keys %changeCount;
my $counter = 0;
my $plural;
my $conjunction = "";
my $punctuation = ", ";
my $moneyType;

foreach ( sort {$b <=> $a} keys %changeCount) {
	
	if ($counter == $hashKeyCount - 1) {
		$conjunction = "and ";
		$punctuation = ".";
	}
	
	if ($changeCount{$_} > 1) {
		$plural = "s";
	} else {
		$plural = "";
	}
	
	if ($_ >= 1) {
		$moneyType = " bill";
	} else {
		$moneyType = "";
	}
	
	printf "%s%d %s%s%s%s", $conjunction, $changeCount{$_}, $changeDenom{$_}, $moneyType, $plural, $punctuation;
	
	$counter++;
}


sub fracMod() {
	my ($a, $b) = @_;
	my $div = $a / $b;
	my $retVal = $a - (int($div) * $b); 
	return $retVal;
}

-------------------------------------------
example 1 (No rounding error):
-------------------------------------------
Enter the Bill Amount: 262.57
Enter the Paid Amount: 500.00
Bill total is  : $262.57
Paid amount is : $500.00
------------------------
Change comes to: $237.43
2 hundred dollar bills, 1 twenty dollar bill, 1 ten dollar bill, 1 five dollar bill, 2 one dollar bills, 1 quarter, 1 dime, 1 nickel, and 3 pennys.

---------------------------------------
example 2 (Rounding error):
---------------------------------------
Enter the Bill Amount: 262.99
Enter the Paid Amount: 500.00
Bill total is  : $262.99
Paid amount is : $500.00
------------------------
Change comes to: $237.01
2 hundred dollar bills, 1 twenty dollar bill, 1 ten dollar bill, 1 five dollar bill, and 2 one dollar bills.
_____________________________________________________________
Seattle Perl Users Group Mailing List
     POST TO: [email protected]
SUBSCRIPTION: http://mail.pm.org/mailman/listinfo/spug-list
    MEETINGS: 3rd Tuesdays
    WEB PAGE: http://seattleperl.org/

Reply via email to