If statements within while loop not giving expected output in C - c

I am making programme to calculate the maximum amount of coins in change given a set amount of change. I take the change demanded as a positive float and convert it into an int by multiplying it by 100, so that the amount is in pennies. Upon testing, some values work but others, such as 4.2, do not, giving the answer 22 when it should be 18. I cannot work out why. Could some please help.
int main (void)
{
float change;
do
{
printf("How much change do you want?\n");
change = get_float();
} while (change < 0);
int change1 = change * 100;
int coins = 0;
while (change1 != 0)
{
if (change1 >= 25)
{
change1 -= 25;
coins++;
}
else if (change1 >= 10)
{
change1 -= 10;
coins++;
}
else if (change1 >= 5)
{
change1 -= 5;
coins++;
}
else if (change1 >= 1)
{
change1 -= 1;
coins++;
}
}
//Print change
printf("%i\n", coins);
}

Roundoff error:
When the machine stores 4.2, it is not exactly 4.2. Thus, when multiplied by 100, it gets to 419.99999..., which converts to the int 419. The way to fix this would be:
int change1 = change * 100 + 0.5;
This could also be checked by
printf("%i\n", change1)
after the calculation.

Hum i just want you show to prefer use ternary operator in this situation :
#include <stdio.h>
int main() {
float number;
int result;
int ctn_coin;
ctn_coin = 0;
printf("How much change do you want?\n");
scanf("%f", &number); result = number * 100.1;
while (result != 0)
{
result >= 25 ? result -= 25 :
result >= 10 ? result -= 10 :
result >= 5 ? result -= 5 :
result >= 1 ? result -= 1 : 0;
ctn_coin++;
}
printf("%i\n", ctn_coin);
return (0);
}

Related

CS50 PSET1 cash.c: I can't seem to get it to print the value I want. Just keeps repeating the input over & over again

Beginner here, and I feel like I am so close to solving this problem but for some reason whenever I run my code, it just keeps asking me over and over again to enter how much change I am owed and doesn't print the amount of coins
The Problem:
Write, in a file called cash.c in ~/workspace/pset1/cash/, a program
that first asks the user how much change is owed and then spits out
the minimum number of coins with which said change can be made
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
float x;
int coin_amount = 0;
do
{
x = get_float("how much change is owed: $");
}
while (x < 0);
while (x >= .25)
{
coin_amount += 1;
x = x - .25;
}
while (x >= .10 && x < .25)
{
coin_amount += 1;
x = x - .10;
}
while (x >= .05 && x < .10)
{
coin_amount += 1;
x = x - .05;
}
while (x >= .01 && x < .05)
{
coin_amount += 1;
x = x - .01;
}
while (x < .01)
{
coin_amount = coin_amount;
}
printf("I have %i coins to give you in change\n", coin_amount);
}
Any idea's in what I am doing wrong? Thank you :)
The main issue with your solution is that the final while() loop - once entered - can not be exited. There are a few other small issues however:
You should be using return 0; to provide a return value for int
main(void)
while (x >= .10 && x < .25) and friends are redundant: you can just use while (x >= .10) (since the second condition
has already been satisfied in the previous while() loop
You can use x -= .25 instead of x = x - .25 (not important and a matter of preference)
Bearing these points in mind, you can try the following ...
#include <stdio.h>
int main(void) {
float x = 0.0;
int coin_amount = 0;
printf("Enter the currency amount: ");
scanf("%f", &x);
printf("You entered: %.4f\n", x);
while (x >= .25) {
coin_amount += 1;
x -= .25;
}
while (x >= .10) {
coin_amount += 1;
x -= .10;
}
while (x >= .05) {
coin_amount += 1;
x -= .05;
}
// Use .00999 instead of .01 due to quirks with floating point math
while (x >= .00999) {
coin_amount += 1;
x -= .01;
}
if (x > 0) {
printf("Ignoring residual value - %.4f ...\n", x);
}
printf("I have %i coins to give you in change\n", coin_amount);
return 0;
}
You haven't specified what your get_float() function is, so I have used scanf() instead.
As Yunnosch initimated in his comment reply, it might be worth considering a solution which doesn't use floating point math also.

Bug in While-Loop Keeps Counting Beyond Condition

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).

Why my program works correctly for some tests and not for others? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 5 years ago.
This is the output of my tests:
:) greedy exists
:) greedy compiles
:( input of 0.41 yields output of 4
expected "4\n", not "3\n"
:( input of 0.01 yields output of 1
expected "1\n", not "0\n"
:) input of 0.15 yields output of 2
:) input of 1.6 yields output of 7
:) input of 23 yields output of 92
:) input of 4.2 yields output of 18
:) rejects a negative input like -.1
:) rejects a non-numeric input of "foo"
:) rejects a non-numeric input of ""
This is the code:
#include <stdio.h>
#include <cs50.h>
void count_coins();
int coin = 0;
float change = 0;
int main(void)
{
do
{
change = get_float("How much change is owed? ");
}
while (change < 0);
count_coins();
printf("%i\n", coin);
}
void count_coins()
{
while (change > 0.24)
{
coin++;
change -= 0.25;
// printf("%.2f\n", change);
}
while (change > 0.09)
{
coin++;
change -= 0.10;
// printf("%.2f\n", change);
}
while(change > 0.04)
{
coin++;
change -= 0.05;
// printf("%.2f\n", change);
}
while (change >= 0.01)
{
coin++;
change -= 0.01;
// printf("%.2f\n", change);
}
}
As Havenard already wrote, the problem is that change was stored as float.
For such a programm change must be stored as an integer value.
This your code with int instead of float:
#include <stdio.h>
#include <cs50.h>
void count_coins (void);
int coin = 0;
int change = 0;
int main (void) {
do {
change = 41; // insert a get integer function here
} while (change < 0);
count_coins();
printf("%i\n", coin);
}
void count_coins (void) {
while (change >= 25) {
coin++;
change -= 25;
}
while (change >= 10) {
coin++;
change -= 10;
}
while(change >= 5) {
coin++;
change -= 5;
}
while (change >= 1) {
coin++;
change -= 1;
}
}

Learning C, need some assistance with "Greedy" CS50 solution

I am very new to C. I come from a python background. I would like to know where I went wrong with my code.
I am doing the cs50 greedy problem. What is wrong with my code? It works with some numbers but others don't work. I am trying to get an input from the user asking how much change to give back, then calculate the minimum number of coins I can give back using only $.25, $.10, $.05, $.01
#include <cs50.h>
#include <stdio.h>
int main(void)
{
float n;
do
{
n = get_float("How much change is owed?\n");
}
while(n == EOF);
int minimumamountofcoins = 0;
if (n/.25 >=1){
do
{
n -= .25;
minimumamountofcoins++;
}
while (n/.25 >= 1);
}
if (n/.1 >=1){
do
{
n -= .1;
minimumamountofcoins++;
}
while (n/.1 >=1);
}
if(n/.05 >=1){
do
{
n -= .05;
minimumamountofcoins++;
}
while (n/.05 >=1);
}
if (n/.01 >=1){
do
{
n -= .01;
minimumamountofcoins++;
}
while (n/.01 >=1);
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}
New code: (works perfectly except when entering 4.2)
#include <cs50.h>
#include <stdio.h>
int main(void)
{
float n;
do
{
n = get_float("How much change is owed?\n");
}
while(n == EOF);
int cents = (int)(n * 100);
int minimumamountofcoins = 0;
if (cents/25 >= 1){
while (cents/25 >= 1)
{
cents -= 25;
minimumamountofcoins++;
}
}
if (cents/10 >= 1){
while (cents/10 >= 1)
{
cents -= 10;
minimumamountofcoins++;
}
}
if(cents/5 >= 1){
while (cents/5 >= 1)
{
cents -= 5;
minimumamountofcoins++;
}
}
if (cents/1 >= 1){
while (cents/1 >= 1)
{
cents -= 1;
minimumamountofcoins++;
}
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}
Since you did not include test cases, I did my own. Here are some of the cases for which your algorithm does not return the correct answer:
.04, .11, .17, .19, .21, .26, .32, etc.
These cases all fail when calculating the number of pennies (in the final do-while loop), and they all return one less coin then they should. This is because of error with floating-point numbers. With print statements, I discovered that when the division for the final penny was being calculated, the same thing occurred each time:
n/.01 = 0.99999999
This is obviously not intended, as this should be equal to 1, and the final penny should be added to the total. Thus, your code, which works in theory, is broken because of floating-point numbers.
To avoid this, you could do any number of things, such as keeping track of dollars and cents separately as integers, change the condition to be n/.01 >= .9999 instead of n/.01 >= 1, treat the amount of money you are doing the calculations on as an integer number of cents, or any other number of things.
Personally, I prefer that last option, treating the amount of money as an integer number of cents. This is easy to do, as all you have to do to convert from dollars to cents is multiply by 100. Thus, the easiest thing to do is to use this same algorithm, except use integers.
Thus, the code would look something like this:
int main(){
float n;
//code that parses in the amount of money, n now stores that amount
int cents = (int)(n * 100);
int minimumamountofcoins = 0;
if (cents/25 >= 1){
while (cents/25 >= 1)
{
cents -= 25;
minimumamountofcoins++;
}
}
if (cents/10 >= 1){
while (cents/10 >= 1)
{
cents -= 10;
minimumamountofcoins++;
}
}
if(cents/5 >= 1){
while (cents/5 >= 1)
{
cents -= 5;
minimumamountofcoins++;
}
}
if (cents/1 >= 1){
while (cents/1 >= 1)
{
cents -= 1;
minimumamountofcoins++;
}
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}

Why are the conditional statements in the while loop causing the program to pause selectively forever?

I am trying to figure out what the minimum number of coins required to pay back change is by using a "greedy algorithm". The program I have written below is working as expected if the user enters a multiple of only one of the constant integers. However, when it comes to to dealing with more than one coin, the program just pauses forever.
I think that the problem is in my CountGreed function's while loop on the conditional statements. I have tried finding answers but nothing I have come across seems to be giving me insight to guide me to understanding what the matter is with my logic.
I know this is trivial and there is repetition in the loop through the conditional statements which then brings me to the stated question. Multiples of 0.25, 0.10, 0.05 and 0.01 are working well if entered by the user. For example, 1.00, 1.25, 0.20 but not 0.30, 1.13, 0.26, etc.
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %i.\n", CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100;
int IntCents = (int)roundf(Cents);
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int SubCoinCount = 0;
int CoinCount = 0;
int Remainder = 0;
while (IntCents) {
if (IntCents >= Quarter) {
SubCoinCount = IntCents / Quarter;
CoinCount += SubCoinCount;
Remainder += IntCents % Quarter;
IntCents = Remainder;
} else if (IntCents < Quarter && IntCents >= Dime) {
SubCoinCount = IntCents / Dime;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
} else if (IntCents < Dime && IntCents >= Nickel) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Nickel;
IntCents = Remainder;
} else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
}
return CoinCount;
}
I pasted the whole main.c file so that the flow of my entire program can be seen clearly though the problem is with the loop. I have tried this on multiple compilers just to make sure that it is my fault.
This:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
should be this:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Penny; // <--- Change to Penny, or just remove
CoinCount += SubCoinCount;
Remainder += IntCents % Penny; // <--- Change to Penny
IntCents = Remainder;
}
Your four if cases are identical except for the denomination of the coin, which means they're crying out to be put into a separate function. Doing that is a great way to avoid making errors like this in one or some of your cases, because you're only writing it once.
I also suspect:
Remainder += IntCents % Dime;
should be:
Remainder = IntCents % Dime;
otherwise Remainder will increase endlessly, and IntCents will never get to zero. Remainder actually becomes unnecessary, in this case, and you can assign the result directly to IntCents.
But there's a simpler way of doing this entirely. Here's a suggested alternative, for your perusal:
#include <stdio.h>
// This cries out to be its own function
int coin_count(int cents, int denomination, int * remainder)
{
*remainder = cents % denomination;
return cents / denomination;
}
// Better way
int CountGreed(int IntCents)
{
static const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
while ( IntCents > 0 ) {
if ( IntCents >= Quarter ) {
CoinCount += coin_count(IntCents, Quarter, &IntCents);
} else if ( IntCents >= Dime ) {
CoinCount += coin_count(IntCents, Dime, &IntCents);
} else if ( IntCents >= Nickel ) {
CoinCount += coin_count(IntCents, Nickel, &IntCents);
} else if ( IntCents >= Penny ) {
CoinCount += coin_count(IntCents, Penny, &IntCents);
}
}
return CoinCount;
}
// Even better way
int CountGreed2(int IntCents)
{
static const int coins[4] = {25, 10, 5, 1};
int CoinCount = 0;
for ( int i = 0; i < 4; ++i ) {
if ( IntCents >= coins[i] ) {
CoinCount += coin_count(IntCents, coins[i], &IntCents);
}
}
return CoinCount;
}
int main(void) {
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed(96));
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed2(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed2(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed2(96));
return 0;
}
which outputs:
paul#local:~/Documents/src/sandbox$ ./coins
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
paul#local:~/Documents/src/sandbox$
The need for a separate function in CountGreed2() is less obvious, since you're only writing it once anyway, but tastes vary.
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %d.\n",
CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
// the original function ConvertToCents()
// will usually return an incorrect value
// typically off by 1
// This is because float values often cannot exactly represent
// the desired value
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100.0f; // note all values should be float
int IntCents = floor(Cents+.5f); // round up to whole penny
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
int Remainder = IntCents; // get working value
// note following using integer divides
CoinCount = Remainder / Quarter; // max quarters
Remainder = Remainder % Quarter; // update working value
CoinCount += Remainder / Dime; // max dimes
Remainder = Remainder % Dime; // update working value
CoinCount += Remainder / Nickle; // max nickles
Remainder = Remainder % Nickle; // update working value
CoinCount += Remainder; // final pennys
return CoinCount;
}

Resources