My task is to write a program to represent an amount of money in different coins.
UPD: I'm allowed to use <stdio.h>
only, modulo
and division
.
The output should be:
Coin Qty Balance
-------- --- ---------
365.5700
Toonies 182 1.5700
Loonies 1 0.5700
Quarters 2 0.0700
Dimes 0 0.0700
Nickels 1 0.0200
Pennies 2 0.0000
But I'm getting this:
Coin Qty Balance
-------- --- ---------
365.5700
Toonies 182 1.5700
Loonies 1 0.5700
Quarters 2 0.0600
Dimes 0 0.0600
Nickels 1 0.0100
Pennies 1 0.0000
This is my code. I cannot get the right calculations with quarters, dimes, nickels and pennies. What have I written wrong? Maybe the issue in type casting.
#include <stdio.h>
int main() {
double total = 365.5700;
int toonies, loonies, quarters, dimes, nickels, pennies;
double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = (int)total / 2;
balToonies = (int)(total * 100) % 200 / 100.0;
// Loonies
loonies = (int)balToonies / 1;
balLoonies = (int)(balToonies * 100) % 100 / 100.0;
// Quarters
quarters = (int)(balLoonies * 100) / 25;
balQuarters = (int)(balLoonies * 100) % 25 / 100.0;
// Dimes
dimes = (int)(balQuarters * 100) / 10;
balDimes = (int)(balQuarters * 100) % 10 / 100.0;
// Nickels
nickels = (int)(balDimes * 100) / 5;
balNickels = (int)(balDimes * 100) % 5 / 100.0;
// Pennies
pennies = (int)(balNickels * 100) / 1;
balPennines = (int)(balNickels * 100) % 1 / 100.0;
printf("Coin Qty Balance\n");
printf("-------- --- ---------\n");
printf("".4lf\n", total);
printf("Toonies = %9.4lf\n", toonies, balToonies);
printf("Loonies = %9.4lf\n", loonies, balLoonies);
printf("Quarters = %9.4lf\n", quarters, balQuarters);
printf("Dimes = %9.4lf\n", dimes, balDimes);
printf("Nickels = %9.4lf\n", nickels, balNickels);
printf("Pennies = %9.4lf\n\n", pennies, balPennines);
return 0;
}
CodePudding user response:
What have I written wrong?
Wrong use of floating point (FP) and integer math by not considering the roundings of FP math and integer truncation and their limitations of representable values.
When a FP result is just under a whole number, like x.99999..., applying (int)
results in x
instead of the desired x 1
.
double
cannot represent values like 365.5700
exactly. Instead a nearby value is used: 365.56999999999999317878973670303821563720703125. That is a whole number * some_power_of_2.
double * 100
often results in a rounded product.
These roundings and OP's casts which truncate result in various off-by-one calculations as compared to the desired result.
Alternative today
A simple alternative is to scale the money by the smallest unit, (which appears to be Can$0.0001 in this case) and use integer math.
Let's go with a wider type than int
, so code can handle small accounts as well as large ones.
#include <math.h>
typedef long long ssymoney;
#define SSYMONEY_SCALE 10000
#define SSYMONEY_FROM_double(d) llround((d) * SSYMONEY_SCALE)
#define SSYMONEY_TO_double(m) ((double)(m) / SSYMONEY_SCALE)
#define SSYMONEY_TOONIE (SSYMONEY_SCALE * 2)
#define SSYMONEY_LOONIE (SSYMONEY_SCALE * 1)
#define SSYMONEY_QUARTER (SSYMONEY_SCALE * 25 / 100)
#define SSYMONEY_DIME (SSYMONEY_SCALE * 10 / 100)
...
int main(void) {
double total = 365.5700;
ssymoney ssytotal = SSYMONEY_FROM_double(total);
long long toonies, loonies, quarters, dimes, nickels, pennies;
ssy_money balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = ssytotal / SSYMONEY_TOONIE;
balToonies = ssytotal % SSYMONEY_TOONIE ;
// Loonies
loonies = balToonies / SSYMONEY_LOONIE;
balLoonies = balToonies % SSYMONEY_LOONIE ;
// quantity = balance / denomination
// money balance_new = balance % denomination
...
printf("".4lf\n", SSYMONEY_TO_double(ssytotal));
printf("Toonies %3lld %9.4lf\n", toonies, SSYMONEY_TO_double(balToonies));
printf("Loonies %3lld %9.4lf\n", loonies, SSYMONEY_TO_double(balLoonies));
...
Alternative later
The next version of C may support decimal floating point. Use that for money.
CodePudding user response:
You can use integer types.
int nominals[] = {100, 25, 10, 5, 1, 0};
void getNominals(double money, int *result)
{
unsigned ncents = money * 100.0;
int *nm = nominals;
while(*nm && ncents)
{
*result = ncents / *nm;
ncents %= *nm ;
}
}
int main(void)
{
int result[sizeof(nominals) / sizeof(nominals[0])] = {0};
getNominals(4.36, result);
for(size_t index = 0; nominals[index]; index )
{
printf("%d = %d\n", nominals[index], result[index]);
}
}
https://godbolt.org/z/3KKbfzh4z
CodePudding user response:
Thank you guys for your help! I have learned a lot. When I made this post I should have mentioned that I'm allowed only <stdio.h>
library and no functions.
I came up with this solution. Please let me know what do you think.
#include <stdio.h>
int main() {
double total = 365.5700;
int toonies, loonies, quarters, dimes, nickels, pennies;
double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = (int)total / 2;
balToonies = (int)(total * 100 0.5) % 200 / 100.0;
// Loonies
loonies = (int)balToonies / 1;
balLoonies = (int)(balToonies * 100 0.5) % 100 / 100.0;
// Quarters
quarters = (int)(balLoonies * 100) / 25;
balQuarters = (int)(balLoonies * 100 0.5) % 25 / 100.0;
// Dimes
dimes = (int)(balQuarters * 100) / 10;
balDimes = (int)(balQuarters * 100 0.5) % 10 / 100.0;
// Nickels
nickels = (int)(balDimes * 100) / 5;
balNickels = (int)(balDimes * 100 0.5) % 5 / 100.0;
// Pennies
pennies = (int)(balNickels * 100);
balPennines = (int)(balNickels * 100 0.5) % 1 / 100.0;
printf("Sales INCLUDING tax\n");
printf("Coin Qty Balance\n");
printf("-------- --- ---------\n");
printf("".4lf\n", total);
printf("Toonies = %9.4lf\n", toonies, balToonies);
printf("Loonies = %9.4lf\n", loonies, balLoonies);
printf("Quarters = %9.4lf\n", quarters, balQuarters);
printf("Dimes = %9.4lf\n", dimes, balDimes);
printf("Nickels = %9.4lf\n", nickels, balNickels);
printf("Pennies = %9.4lf\n\n", pennies, balPennines);
return 0;
}