Counting Change Program - C - c

I ran into a peculiar problem when trying to write a program for counting out change for a user. The user would enter in an amount -- in dollars and cents -- and the program would compute how many bills and coins the user would receive.
I have issues with counting out the coins portion, as I am not calculating the amount I expect to be calculating.
For example, the user would input 123.45 so I would pull the 123 out and compute the dollars portion, and then pull the .45 and compute the coins portion.
I feel like there is an issue with casting a floating-point number to an integer, but I'm not sure. If I enter .45 and then try and print it, the program would output .449997 instead.
What's going on here?
#include <stdio.h>
void giveChange(float);
void countCents(float);
int main()
{
float amount;
printf("Enter in an amount (in dollars and cents): ");
scanf("%f", &amount);
giveChange(amount);
getchar();
return 0;
}
void giveChange(float amount)
{
int newAmount = (int)amount;
int hundreds, fifties, tens, fives, ones;
float cents = amount - newAmount;
hundreds = newAmount / 100;
newAmount %= 100;
fifties = newAmount / 50;
newAmount %= 50;
tens = newAmount / 10;
newAmount %= 10;
fives = newAmount / 5;
newAmount %= 5;
printf("\nHundreds: %i\nFifties: %i\nTens: %i\nFives: %i\nOnes: %i\n", hundreds, fifties, tens, fives, newAmount);
countCents(cents);
return;
}
void countCents(float cents)
{
int newCents = cents * 10;
int quarters, dimes, nickels, pennies;
quarters = newCents / 25;
newCents %= 25;
dimes = newCents / 10;
newCents %= 10;
nickels = newCents / 5;
newCents %= 5;
printf("\nQuarters: %i\nDimes: %i\nNickels: %i\nPennies: %i\n", quarters, nickels, dimes, newCents);
return;
}

You are using floating-point data types to represent fixed-point calculations. Floating-point arithmetic is subject to a number of rounding errors such as those you've seen.
Instead of using float or double to represent dollars and fractions, use a plain int representing the total amount of cents. For example, instead of using float value = 4.25; for $4.25, use int value = 425; (425 cents) instead. Then, value/100 (== 4) is the number of dollars (note: integer division is truncated), and value%100 (== 25) is the number of pennies.
(This is called 'fixed-point' since the decimal point position is fixed in the representation (in this case, it is always after exactly two decimal digits). Fixed-point arithmetic is basically integer arithmetic with post-calculation corrections.)

You can't represent change with a float. You need to treat money as an integral number of cents (or tenths of a cent, hundredths of a cent, &ct depending on application).
Try something like this.
#include <stdio.h>
int main (void)
{
int dollars;
int cents;
scanf ("%d.%d", &dollars, &cents);
printf ("%d dollars, %d cents\n", dollars, cents);
return 0;
}

Long story short floats do not work like ints and thus you cannot express precise numbers with them.
See here.
Try multiplying the input by 100 and then using %100!

Related

I came up with my own version of "Cash" problem from CS50x, can I optimize it? [duplicate]

This question already has answers here:
Cannot figure out how to properly increment a variable inside of a while loop, C
(2 answers)
Closed 2 years ago.
So basically, cash is a problem where you need to code a program that counts how many coins there is in a set sum.
For instance : for 0.41$, the minimum coins you can owe is 4 (1 quarter, 1 dime, 1 nickel, 1 penny).
The exercise will ask you just to code something that will answer : 4 for the entry "0.41"
I changed a bit the program so it answers for 4.2$ for example :
"16 quarter(s)
2 dime(s)
0 nickel(s)
0 penny(ies)" and was wondering if there is a way to optimize the code and make it better ?
Here is the code :
#include <cs50.h>
#include <math.h>
int main(void)
{
//Prompt user for an amount of change
float n;
do
{
n = get_float("How much change is owed for : (in $)\n");
//Verify if the float is positive
}
while (n < 0);
//Multiply 'n' by 100 to avoid float imprecisions
int cent = round(n * 100);
// Initialize the number of quarters (zero initially)
int quarters = 0;
while (cent >= 25)
{
quarters++;
cent = cent - 25;
}
// Initialize and calculate the number of dimes (zero initially)
int dimes = 0;
while (cent >= 10)
{
dimes++;
cent = cent - 10;
}
// Initialize and calculate the number of nickels (zero initially)
int nickels = 0;
while (cent >= 5)
{
nickels++;
cent = cent - 5;
}
// Initialize and calculate the number of pennies (zero initially)
int pennies = 0;
while (cent >= 1)
{
pennies++;
cent = cent - 1;
}
//Print the results
printf("%i quarter(s)\n", quarters);
printf("%i dime(s)\n", dimes);
printf("%i nickel(s)\n", nickels);
printf("%i penny(ies)\n", pennies);
}
As suggested by #MikeCAT, it'd be great to change it such that you use division and the modulo operator. This way, you'll avoid your while loop saving a few operations. Further, as #Weather Vane suggested, you can also have an array of multiple coin values and a singular loop. It'd also be great to print the coins depending on what all denominations there are. It would also be nice to determine the number of denominations (n_denomintations) at runtime. The code for the same would look like:
int cent = round(n * 100);
int denominations[n_denominations] = {25, 10, 5, 1}; // coins in descending order, alternatively ascending order and iterate in opposite
int n_denominations = sizeof(prices) / sizeof(prices[0]); // how many denominations of coins
int coins[n_denominations];
for (int i = 0; i < n_denomintations; i++) {
coins[i] = cent / 25; // implicitly typecasts to int, meaning that quarters will get whatever value cent / 25 is, rounded down
cent = cent % denominations[i]; // will give whatever amount remains after removing quarters
}
for (int i = 0; i < n_denominations; i++) {
printf("%i cent coins: %i\n", denomintations[i], coins[i]);
}

Inconsistencies when calculating the remainder where 220 % 25 gives a remainder of 20 while 420 % 25 gives a remainder of 19? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Why not use Double or Float to represent currency?
(16 answers)
How to represent currency or money in C
(5 answers)
How to read and store currency values in C [duplicate]
Closed 2 years ago.
As a part of the CS50 course we're tasked to create a program (in C) that calculates the least amount of coins ($0.25, $0.10, $0.05 and $0.01) from a value submitted by the user.
My idea was to take the input value and multiply by 100 and use integers since the only value of interest is the number of coins and not the monetary value, hence I don't have to tinker with any decimals.
The code is:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
//If it's NOT a positive number, do this.
float n;
do
{
n = get_float("Change owed: \n");
}
while (n <= 0);
//Multiplying change owed with 100 to avoid having to deal with decimals.
int cash = n * 100;
//Calculating the number of quarters ($0.25).
int quarters = cash / 25; //How many full quarters per cash.
int quarters_rem = cash % 25; //The remainder after full amout of quarters in cash.
printf("Number of quarters: %i\n", quarters); //Test how many quarters.
printf("Remainder: %i\n", quarters_rem); //Test how much remainder.
//Calculating the number of dimes ($0.10).
int dimes = quarters_rem / 10; //How many full dimes from the remainder when all quarters are deducted.
int dimes_rem = round(quarters_rem % 10); //The remainder after full amount of dimes in quarters_rem.
printf("Number of dimes: %i\n", dimes); //Test how many dimes.
printf("Remainder: %i\n", dimes_rem); //Test how much remainder.
//Calculating the number of nickels ($0.05).
int nickels = dimes_rem / 5; //How many full nickels from the remainder when all dimes are deducted.
int nickels_rem = round(dimes_rem % 5); //The remainder after full amount of nickels in dimes_rem.
printf("Number of nickels: %i\n", nickels); //Test how many nickels.
printf("Remainder: %i\n", nickels_rem); //Test how much remainder.
//Calculating the number of cents ($0.01).
int cents = nickels_rem; //How many full cents from the remainder when all nickels are deducted.
printf("Number of cents: %i\n", cents); //Test how many nickels.
//Prints the least number of coins to be returned.
int coins = quarters + dimes + nickels + cents;
printf("%i\n", coins);
}
The thing is that when I run the code and enter 2.2, 6.2 or 8.2, the output gives me a remainder of 20 after calculating the quarters. 2.2 x 100 = 220 -> 25 x 8 = 200 which gives a remainder of 20, as expected. This is true for 2.2, 6.2, 8.2, 10.2, 12.2, 14.2 and so on.
However, this is not! true if I enter 4.2! If I enter 4.2 I expect: 4.2 x 100 = 420 -> 25 x 16 = 400 which ought to give me a remainder of 20, but instead I get a remainder of 19? I don't understand why the remainder is 19 in this instance but 20 in the others?
Typical implementation of floating-point stores numbers in binary format, so it cannot precisely store some of decimal numbers.
With this program
#include <stdio.h>
int main(void) {
float x = 4.2;
float y = x * 100;
printf("%.10f\n", y);
return 0;
}
I got output:
419.9999694824
This shows that 4.2f * 100 became slightly smaller than 420 and converting that to int will result in 419 instead of 420.
To avoid this, you should add smaller value before converting float to int in this case.
int cash = n * 100 + 0.1;

New at programming, off by a penny? in C [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 5 years ago.
Hi so I'm struggling to figure out what's wrong with my code. I'm really new at this so bear with me. Comments might be a little messy atm.
#include <stdio.h>
int main(void)
{
double cost, gstCost, newCost; // initial cost, cost of gst by itself, new cost after gst
int loonies, quarters, dimes, nickels, pennies; // used for quantity of coins
float loonreq, quartreq, dimereq, nickreq, penreq; // cost required after deduction of the corresponding coin
printf("Please enter the amount to be paid: $");
scanf("%lf", &cost); // scanf allows to input an amount as a double ("%lf")
gstCost = cost * .13 + .005; // .13 for gst and add 0.005 to round up or down
printf("GST: %.2lf\n", gstCost);
newCost = cost + gstCost;
printf("Balance owing: $%.2lf\n", newCost); // original cost + gst cost
loonies = newCost; // loonies will output as integer when cost has decimals
printf("Loonies required: %d", loonies);
if (loonies == 0) // == used to compare equality
loonies = 1; // if loonies = 0, loonreq will be infinite causing code to crash and stop
loonreq = (float)((int)(100 * newCost) % (100 * loonies)) / 100; // casting int and * 100 on float values for modulo since it can only calculate for integer value
printf(", balance owing $%.2f\n", loonreq); // %.2f shows a float with 2 decimal places
quarters = 100 * loonreq / 25; // 100*loonreq allows the code to find how many quarters by dividing by 25
printf("Quarters required: %d", quarters);
if (quarters == 0)
quarters = 1;
quartreq = (float)((int)(100 * loonreq) % (int)(100 * (quarters * .25))) / 100;
printf(", balance owing $%.2f\n", quartreq);
dimes = 100 * quartreq / 10;
printf("Dimes required: %d", dimes);
if (dimes == 0)
dimes = 1;
dimereq = (float)((int)(100 * quartreq) % (int)(100 * (dimes * .10))) / 100;
printf(", balance owing $%.2f\n", dimereq);
nickels = 100 * dimereq / 5;
printf("Nickels required: %d", nickels);
if (nickels == 0)
nickels = 1;
nickreq = (float)((int)(100 * dimereq) % (int)(100 * (nickels * .05))) / 100;
printf(", balance owing $%.2f\n", nickreq);
pennies = 100 * nickreq / 1;
printf("Pennies required: %d", pennies);
if (pennies == 0)
pennies = 1;
penreq = (float)((int)(100 * nickreq) % (int)(100 * (pennies * .01))) / 100;
printf(", balance owing $%.2f\n", penreq);
return 0;
}
When I run this code on Visual Studio, I get the correct outputs for certain inputs like 8.68 but when I submit this file through PuTTY for my professor, it tests it for me and I get an incorrect balance (a penny off) after dimes deducted. When I put in a value like 76.54, I'm a penny off after the deduction of loonies. Inputting a value like 76.76, I get the correct output. I don't exactly know what's happening. My professor looked at my code and said it's because of type changes? and recommended that I use this method instead, example
dimes = (balance / 100) / 0.1;
balance = (int)(balance) % 10;
I'm not sure how to use this method though.
Edit: I need to use the modulus operator and casting for this assignment. gcc is used when I submit on PuTTy.
The rounding logic is not giving the correct answer. Say we have an input 123. The GST should be 15.99. However your code will give 16.00. To fix this try replacing gstCost = cost * .13 + .005; with gstCost = (round(cost * .13 * 100) / 100);
Don't use float/double at all for money. Computers are binary and use base 2 math. Not all decimal values (base 10) can be represented precisely in base 2 floating point, causing rounding errors. Do your math with int (or long long) representing pennies and it will be accurate up to the max value of a 32-bit signed int (millions) or 64-bit signed long long (quadrillions).
(float)((int)(100 * quartreq) % (int)(100 * (dimes * .10))) / 100;
I'm sure that changing types like float to int and vise versa can lose a some data throught the parsing part.
example: you have a double variable set as 1.2 when you parse it to int it become 1 and not 1.2 and it won't become 1.2 when you parse it back to double.
Do your calculations with the float type and if you want to change data type only parse it in the final result.

Integer overflow in greedy coin counting

#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void) {
printf ("Enter amount: ");
float amount = GetFloat();
int coins = 0;
while (amount != 0) {
if (fmod(amount, 0.25) == 0) {
amount = amount - 0.25;
coins += 1;
}
else if (fmod(amount, 0.10) == 0) {
amount = amount - 0.10;
coins += 1;
}
else if (fmod(amount, 0.05) == 0) {
amount = amount - 0.05;
coins += 1;
}
else {
amount = amount - 0.01;
coins += 1;
}
}
printf ("Coins : %d\n", coins);
}
I'm trying to implement a small greedy algorithm, in which a user inputs an amount of money ( Ex: 9.25 ) and we output the least amount of coins that it takes for us to exchange it in change( 25 cents, 10 cents, 5 cents and 1 cent only).
This algorithm works with int amounts like 10 or 20 and with amounts that only requires the program to use the 25 cents coins.
If I try an amount like 9.10 or 9.01, I get a runtime error, signed integer overflow. I understand what it means, but I don't understand how can the value of coins go so high all of a sudden.
As Danial Tran said it is better to use int when you do logical operations. Please read Why not use Double or Float to represent currency? Also you can avoid while loop.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void) {
printf ("Enter amount: ");
//float amount = GetFloat(); //Please refer to chqrlie's comments below.
double amount = 0.0;
scanf("%lf",&amount); //I don't know GetFloat() equivalent for double. So using scanf().
long long int amountInt = (long long int) (amount * 100.0);
int coins = 0;
if (25 <= amountInt) {
coins += (amountInt/25);
amountInt = amountInt % 25;
}
if (10 <= amountInt) {
coins += (amountInt/10);
amountInt = amountInt % 10;
}
if (5 <= amountInt) {
coins += (amountInt/5);
amountInt = amountInt % 5;
}
if (1 <= amountInt) {
coins += amountInt;
}
printf ("Coins : %d\n", coins);
}
It seems that no one has answered the particular question
If i try an amount like 9.10 or 9.01, i get a runtime error,signed integer overflow, i understand what it means, but i don't understand how can the value of coins go so high all of a sudden.
so for the sake of completeness, partially as an exercise:
You can find the reason using a debugger. I copied your code and found that it runs for very long. Interrupting it a moment after start revealed that the code freezes repeating this check:
if (fmod(amount, 0.25) == 0) {
amount = amount - 0.25;
coins += 1;
}
At the moment of the interruption amount was about minus 1.2 million and coins almost 5 million. This clearly shows one thing you failed to check: negativity. It can happen easily with floats that you miss the exact zero, as the others have correctly reasoned, no need to repeat that. But if that happens, your program should get worried the moment amount gets negative. Otherwise, under the right conditions, it may as well keep subtracting its way towards negative infinity, and yes, integer overflow will happen in coins.
This is because the computer represent the decimals in binary (power of 2)
For 0.25, the computer can represent it properly in binary. This is because we can obtain 0.25 exactly using power of 2's.
However for 0.10 ( or other denominations mentioned ), they cannot be expressed exactly in powers of 2.
Suppose you try to obtain 0.1 using power of 2's , you won't be able to obtain it exactly. You can just go near it.
0.1 = 0.0625 ( 2^4 ) + 0.03125 ( 2^5 ) + 0.00390625 ( 2^-8) +...
You will approach 0.1 , but you'll never reach 0.1 exactly.
Float, double everyone has a fixed number of bits to represent a decimal. So it will keep only those many bits, whose sum would be slightly less than 0.1
If you want to follow the same approach, you can have 2 possible solutions :-
Use (amount > 0) instead of (amount != 0), or
Use currencies which can be expressed easily in powers of 2 e.g. 0.25, 0.125 , 0.375 , 0.06125.
Your algorithm is not correct:
For example with 30 cents you can exchange to: 25+5 (2 coins) with your algorithm it would be 10+10+10 (3 coins). So greedy means why it's greater than 25 cents then exchange to 25 cents first.
while (amount != 0) {
if (amount >= 0.25) {
amount = amount - 0.25;
coins += 1;
}
else if (amount >= 0.10) {
amount = amount - 0.10;
coins += 1;
}
else if (amount >= 0.05) {
amount = amount - 0.05;
coins += 1;
}
else {
amount = amount - 0.01;
coins += 1;
}
}
If you want to do that way.
Better way:
int coinTypes[] = {0.25, 0.1, 0.05, 0.01};
for (int i = 0; i < 4; i++) {
coins += floor(amount / coinTypes[i];
amount -= coins * coinsTypes[i];
}
The main problem with your algorithm is invalid usage of fmod function. According to definition the result of fmod(num, denom) is
fmod = num - floor(num/denom) * denom
where floor(num/denom) is integer.
Thus, fmod(9.10, 0.25) == 0.1, fmod(9.10, 0.10) == 0.1.
In addition, the manipulation with floating point number rarely gives exact results. so amount is never 0.
You cannot compute this with the float type. Amounts that are not exact multiples of 0.25 cannot be represented exactly in either the float or the double type.
You can fix this problem by computing an exact number of cents and dispatch it using integer arithmetics:
#include <stdio.h>
#include <math.h>
void print_coins(int coins, const char *singular, const char *plural) {
if (coins > 0)
printf(" %d %s", coins, coins > 1 ? plural : singular);
}
int main(void) {
for (;;) {
double amount;
int amountInt, coins, quarters, dimes, nickels, pennies;
printf("Enter amount: ");
if (scanf("%lf", &amount) != 1 || amount <= 0)
break;
amountInt = (int)(amount * 100.0 + 0.5);
quarters = amountInt / 25;
amountInt %= 25;
dimes = amountInt / 10;
amountInt %= 10;
nickels = amountInt / 5;
amountInt %= 5;
pennies = amountInt;
amountInt = 0;
coins = quarters + dimes + nickels + pennies;
printf("coins returned: %d:", coins);
print_coins(quarters, "quarter", "quarters");
print_coins(dimes, "dime", "dimes");
print_coins(nickels, "nickel", "nickels");
print_coins(pennies, "penny", "pennies");
printf("\n");
}
return 0;
}
Notes:
Using float without the + 0.5, the change is incorrect for as little as 100.10: one penny short.
Using float, the change is incorrect for 1000000.10: 3 extra pennies.
To handle amounts above 20 million dollars, you need a larger integral type such as long long int. With that, you can handle amounts exceeding the US national debt.

C program to calculate change

I am trying to write a program to calculate change, but it doesn't seem to work.
I think that the problem is the owed 1/ paid 1; when I tried to print there values I got nothing (0).
Any help ?
#include <stdio.h>
int main()
{
double owed, paid;
int dollars, quarters, dimes, nickels, cents, remainder, owed1, paid1;
printf("how much did the customer have to pay ?\n");
scanf("%f",&owed);
printf("how much did the customer pay ?\n");
scanf("%f",&paid);
owed1 = owed * 100;
paid1 = paid * 100;
int change = paid1 - owed1;
dollars = change / 100;
remainder = change % 100;
quarters = remainder / 25;
remainder = remainder % 25;
dimes = remainder / 10;
remainder = remainder % 10;
nickels = remainder / 5;
remainder = remainder % 5;
cents = remainder;
printf("%d",dollars);
printf("Dollars:%d, Quarters:%d, Dimes:%d, Nickels:%d, Cents:%d", dollars , quarters , dimes , nickels , cents );
return 0;
}
You're using %f in your scanf, which is the format specifier for a float, but your variables are doubles. You should use %lf instead:
scanf("%lf",&owed);
Same thing for paid. You should be getting warning from your compiler about that.

Resources