Bug in While-Loop Keeps Counting Beyond Condition - c

For school I am to write a C program that takes some amount of cash and returns the smallest number of coins it would take to reach that amount. I don't know what I am doing wrong. I've been tweaking and trying all sorts of different things but I cannot seem to totally debug the program.
The program gives correct answers to some inputs but overstates the amount of coins needed for many inputs.
Here is what I have so far.
#include <stdio.h>
int main()
{
float cash;
int n;
int counter=0;
int quarters=0;
int dimes=0;
int nickels=0;
int pennies=0;
for (;;)
{
printf("Enter change amount: ");
scanf("%f",&cash);
if (cash > 0)
{
break;
}
}
n = cash * 100;
counter = 0;
while (n > 0)
{
while (n >= 25)
{
counter ++;
n = n - 25;
quarters ++;
printf("%i\n",n);
}
while (n >= 10 && n < 25)
{
counter ++;
n = n - 10;
dimes ++;
printf("%i\n",n);
}
while (n >= 5 && n < 10)
{
counter ++;
n = n - 1;
nickels++;
printf("%i\n",n);
}
while (n > 0 && n < 5)
{
counter ++;
n = n - 1;
pennies ++;
printf("%i\n",n);
}
}
printf("%d\n",counter + n);
printf("%i quarters, %i dimes, %i nickels, %i pennies\n",
quarters, dimes, nickels, pennies);
return 0;
}

I'm a bit surprised they're wanting you to use break to exit a loop, as you usually want loops to conclude "naturally" (and you usually save breaks for switch statements). Something like this should work, using integer division and the modulus operator (edit note: I'm using two ints instead of a single float because of inaccuracy with the latter. If someone more knowledgeable wants to show how to do it with float, would be interesting.):
#include <stdio.h>
int main() {
int dollar, cent;
int q = 0;
int d = 0;
int n = 0;
int p = 0;
int re;
printf("Enter amount: ");
scanf(" %d.%d", &dollar, &cent);
q = dollar * 4;
re = cent;
q = q + (re / 25);
re = re % 25;
d = re / 10;
re = re % 10;
n = re / 5;
re = re % 5;
p = re;
printf("q %d d %d n %d p %d\n", q, d, n, p);
return 0;
}
This approach also works if, for example, you're given the seconds and want to find the min:sec from that. If you're given 65 seconds, you do 65 / 60 for the minutes portion (which is 1), and the seconds portion is just the remainder after you divide by 60, or 65 % 60 (which is 5).

Here is a more complete answer that fits with the code that you gave us to start with. I changed the loops to subtraction/multiplication and fixed the bug where you were treating nickels as pennies. You don't need the counter variable anymore, but I left it in.
#include <stdio.h>
int main()
{
float cash;
int n;
int counter=0;
int quarters=0;
int dimes=0;
int nickels=0;
int pennies=0;
for (;;)
{
printf("Enter change amount: ");
scanf("%f",&cash);
if (cash > 0)
{
break;
}
}
n = cash * 100;
counter = 0;
if (n > 0)
{
quarters = (int)floor(n / 25);
n -= quarters*25;
printf( "%i\n", n );
dimes = (int)floor(n / 10);
n -= dimes*10;
printf("%i\n",n);
nickels = (int)floor(n / 5);
n -= nickels*5;
printf("%i\n",n);
pennies = n;
printf("%i\n",n);
}
printf("%i quarters, %i dimes, %i nickels, %i pennies\n",
quarters, dimes, nickels, pennies);
return 0;
}

First of all, try start with abstracting out how to handle one type of coin:
int coinsNeeded( int amount, int coinAmount )
{
return (int) floor( amount / coinAmount );
}
Then, handle each coin separately:
quarters = coinsNeeded( cash, 25 );
cash -= (quarters * 25);
Just repeat that for each type of coins you want to consider, and then print out the information at the end. There is some disagreement about whether you want to use floating points or not. Floating points do have rounding errors that you want to avoid when using money. what you actually need is a fixed point data type, but I digress. You can get close enough by doing it the way you're doing it (multiplying by 100 and just dealing with pennies).

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]);
}

C calculation result incomprehensible

Why I can not get a result of 2 while giving input of 2.2 as a float.
With my code, 2.2 should get converted to 220, and when it goes through the first for loop I should get a remainder of 20 (which is fine as it gives me 8 coins).
But when it goes through the second loop, I can not get 20/10 = 2, I always get 1.
By the way if I just put dime <= 20, I will get 2 hmm. I don't understand why since the remainder is equal to 20 as well.
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
float change ;
float quarter ;
float dime ;
float nickel ;
float penny = 1;
int coins = 0;
int coins1 = 0;
int coins2 = 0;
int coins3 = 0;
int sum = 0;
int remainder ;
do
{
printf("What is the owed change: \n");
change = GetFloat();
change = round(change * 100);
printf("%f\n", change);
}
while(change < 0);
for(quarter = 25; quarter <= change; quarter+=25)
{
remainder = change - quarter;
coins++;
}
printf("%d,%d\n", remainder,coins);
for (dime = 10; dime <= remainder; dime += 10) //This is where the problem starts.
{
remainder = remainder - dime;
coins1++;
}
printf("%d,%d\n", remainder,coins1);
for (nickel = 5; nickel < remainder; nickel += 5)
{
remainder = remainder - nickel;
coins2++;
}
printf("%d,%d\n", remainder,coins2);
for (penny = 1; penny < remainder; penny += 1)
{
remainder = remainder - penny;
coins3++;
}
printf("%d,%d\n", remainder,coins3);
printf("\n%d\n", sum = coins + coins1 + coins2 + coins3);
}
You're subtracting dime from remainder during each run of the for loop, while dime is being increased during each iteration of the loop. Let's suppose that change is initially 20 before the second for loop. The first loop execution will subtract 10, leaving remainderas 10. Then dime is incremented by 10 and is now 20. The loop condition fails because 20 > 10, and the loop runs only once.
My advice is to give your variables more intuitive names, like i or x for basic loop counters and dimes_needed instead of coins1

Calculate the power of e (e^x), why n = 999?

Well, I was looking on the net for a code to calculate the power of e (e^x) and found a few good codes for that. Then I found the following code and just wants to know what the n = 999 part and n <= 100 part are supposed to do? I mean.. why n <= 100? why n = 999?
#include<stdio.h>
#define ACCURACY 0.0001
int main() {
int n, count;
float x, term, sum;
printf("\nEnter value of x :");
scanf("%f", &x);
n = term = sum = count = 1;
while (n <= 100) {
term = term * x / n;
sum = sum + term;
count = count + 1;
if (term < ACCURACY)
n = 999;
else
n = n + 1;
}
printf("\nTerms = %d Sum = %f", count, sum);
return 0;
}
It's just a sum of terms in a series.
The term < ACCURACY test just looks to see if the desired accuracy was reached. If not, it goes to the next term in the series. If yes, n = 999 just makes the loop end. You could put there break; with the same result.

What's wrong with my code (CS50 2012 Pset 1 greedy)

I am trying to make a program that gives the least amount of coins for change but if I give a number other than something that divides into quarters, it fails miserably. For example, if I input 1.25, I get 5 quarters but if I input 1.26, I get 5 quarters 1 nickel which is of course incorrect. What am I doing wrong?
#include <stdio.h>
#include <cs50.h>
#include <math.h>
void calculate_change(change_requested){
int num_quarters = 0;
int num_dimes = 0;
int num_nickles = 0;
int num_pennies = 0;
int val_quarters = 25;
int val_dimes = 10;
int val_nickles = 5;
num_quarters = floor(change_requested/val_quarters);
if(change_requested % val_quarters != 0){
num_dimes = floor( (change_requested - (num_quarters * val_quarters))/val_dimes );
if( change_requested - (((num_quarters * val_quarters) + (num_dimes * val_dimes))) != 0){
num_nickles = floor( change_requested - ( (num_quarters * val_quarters) + (num_dimes * val_dimes)/val_nickles ));
if( change_requested - (((num_quarters * val_quarters) + (num_dimes * val_dimes) + (num_nickles * val_nickles))) != 0){
for(int i = 0; i<change_requested - (((num_quarters * val_quarters) + (num_dimes * val_dimes) + (num_nickles * val_nickles))); i++){
num_pennies++;
}
}
}
}
if(num_quarters > 0){
printf("%i Quarters ",num_quarters);
}
if(num_dimes > 0){
printf("%i Dimes ",num_dimes);
}
if(num_nickles > 0){
printf("%i Nickles",num_nickles);
}
if(num_pennies > 0){
printf("%i Pennies",num_pennies);
}
printf("\n");
}
int main (void){
printf("How Much Change Do You Need?\nAmount: ");
float change_requested = GetFloat();
calculate_change(change_requested * 100);
return 0;
}
I feel you are overcomplicating this. If you need to write
for(int i = 0; i<change_requested - (((num_quarters * val_quarters) + (num_dimes * val_dimes) + (num_nickles * val_nickles))); i++){
and all this in one line, then something is certainly wrong. You can do this in a much simpler way, by subtracting the value of the coins just calculated from the total amount in order to to obtain the rest:
int vals[] = { 25, 10, 5 };
const char *names[] = { "quarters", "dimes", "nickles" };
int pennies = 100 * GetFloat(); // not good at all, btw (*)
for (int i = 0; i < 3; i++) {
int n = pennies / vals[i];
if (n) {
printf("%d %s ", n, names[i]);
}
pennies -= n * vals[i];
}
if (pennies)
printf("%d pennies", pennies);
printf("\n");
As to why GetFloat() is not good: floating-point numbers aren't exact, so, for example, 1.26 may be actually represented as something like 1.25999946. When you convert this to an integral value, you may lose a penny or so due to truncation if you are unlucky.
Your parentheses are off in your code. Take a look at this line:
num_nickles = floor( change_requested - ( (num_quarters * val_quarters) + (num_dimes * val_dimes)/val_nickles ));
Your code is first going to evaluate (num_quarters * val_quarters) which comes out to 125. Then it evaluates (num_dimes * val_dimes) which comes out to 0. Then it divides (num_dimes * val_dimes) by val_nickles which also comes out to 0 and then adds that 0 to (num_quarters * val_quarters). Thus what that line of code essentially works out to is:
num_nickles = floor( 126 - 125 + 0) which turns out to be 1.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// four kinds of coins as constant variables
const int quarter = 25, dime = 10, nickel = 5;
float change;
unsigned int changeCoin, count, reminder;
do
{
printf ("O hai! How much change is owned?\n");
change = GetFloat();
}
while (change < 0);
// convert input into cents
changeCoin = round (change * 100);
// count the coins
count = changeCoin / quarter;
reminder = changeCoin % quarter;
count += reminder / dime;
reminder %= dime;
count += reminder / nickel;
reminder %= nickel;
count += reminder;
printf ("%d\n", count);
}

I need help getting this program to properly print my outputs

#include <stdio.h> /*printf and scanf option*/
#include <math.h>
void change(double coin_change, int *quarters, int *dimes, int *nickels, int *pennies); /*function protype*/
int main(void)
{
int fifties = 0, twenties = 0, tens = 0, fives = 0, dollars = 0, quarters = 0, dimes = 0, nickels = 0, pennies = 0;
double amt_paid = 0, amt_due = 0, amt_change = 0, coin_change = 0; /*declared avriables*/
printf("Enter the amount paid> "); /*Prompt user to enter amount paid*/
scanf("%lf", &amt_paid);
printf("Enter the amount due> "); /*Prompt user to enter amount due*/
scanf("%lf", &amt_due);
amt_change = amt_paid - amt_due; /*Formula for amount of change to be given*/
dollars = (amt_change);
coin_change = (int)((amt_change - (amt_change)) * 100 + 0.5);
coin_change = coin_change * 100;
printf("\n%f\n", coin_change);
change(coin_change, &quarters, &dimes, &nickels, &pennies);
printf("Change is fifties: %d$, twenties: %d$, tens: %d$, fives: %d$, dollars: %d$, quarters: %d, dimes: %d, nickels: %d,\
pennies: %d", fifties, twenties, tens, fives, dollars, quarters, dimes, nickels, pennies);
return(0);
}
void change(double coin_change, int *quarters, int *dimes, int *nickels, int *pennies)
{
int q = 1, d = 1, n = 1, p = 1;
do {
if(coin_change >= 25){
*quarters = *quarters + q;
coin_change = coin_change - 25;
}
else if (coin_change >= 10) {
*dimes = *dimes + d;
coin_change = coin_change - 10;
}
else if (coin_change >= 5) {
*nickels = *nickels + n;
coin_change = coin_change - 5;
}
else if (coin_change >= 1) {
*pennies = *pennies + p;
coin_change = coin_change - 1;
}
} while (coin_change >= 1);
}
I'm sorry I wasn't very clear the first time. What I need is to create what is basically a cash register program. When given the amount due, and the amount paid from the user, i should receive output that tell me how many 50 dollar bills, 20s, 10s, 5s, 1s, quarters, dimes, nickels, and pennies I should be receiving as change. As I am new to programming, the code you see is what is to the best of my knowledge. I do need to improve or even completely change it. What I am really looking to do is pinpoint my mistakes, and fix them. I am hoping to have this code done soon. I feel that I am close, but only just missing it. Maybe I am wrong, but that is what I am coming to you guys for.
A couple of things:
you have many unused variables: fifties, twenties, tens, fives, dollars, etc.
The lines here:
coin_change = (int)((amt_change - (amt_change)) * 100 + 0.5);
coin_change = coin_change * 100;
Are wrong. They should be replaced with something like the following:
coin_change = (100 * amt_change).
Have you heard of the += / -= operators? They'd turn these lines:
*quarters = *quarters + q;
coin_change = coin_change - 25;
Into this:
*quarters += q;
coin_change -= 25;
After I fixed those things, your code worked fine.
I don't want to write the code for you because this smells like homework, but here's the algorithm:
read_from_keyboard(amount_due)
read_from_keyboard(amount_paid)
change = amount_paid - amount_due
for each denomination in (
fifties, twenties, tens, fives, ones, quarters, dimes, nickels, pennies) {
while (change >= value of denomination) {
increment counter for denomination
subtract value of denomination from change
}
print counter + name of denomination // Ex: "4 twenties"
}
The "trick" is to realize that you can treat whole dollar values and coins in exactly the same way -- part of the art of programming is being able to find a generic solution that you can re-use, rather than handling each situation as a special case.
You may want to convert the change to an integer that represents the value in cents, so you can avoid the rounding errors that floating-point arithmetic creates.
Good luck!

Resources