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);
}
Related
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, ¢);
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).
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);
}
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
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;
}
I have been using Ubuntu 12.04 LTS with GCC to compile my the codes for my assignment for a while. However, recently I have run into two issues as follows:
The following code calculates zero for a nonzero value with the second formula is used.
There is a large amount of error in the calculation of the integral of the standard normal distribution from 0 to 5 or larger standard deviations.
How can I remedy these issues? I am especially obsessed with the first one. Any help or suggestion is appreciated. thanks in advance.
The code is as follows:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 599
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int p = 0, k, z[5] = {0, 3, 5, 10, 20};
long double sum1[5] = {0}, sum2[5] = {0} , factor = 1.0;
for (p = 0; p <= 4; p++)
{
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z[p], 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1[p] += summand1[k];
}
//Wolfamalpha site gives the same value here
for (k = 0; k <= N; k++)
{
factor *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) ) * powl(z[p], 2 * k + 1) / factor);
//printf("%Le \n", factor);
sum2[p] += summand2[k];
}
sum2[p] = sum2[p] * expl((-powl(z[p],2)) / 2);
}
for (p = 0; p < 4; p++)
{
printf("The sum obtained for z between %d - %d \
\nusing the first formula is %Lf \n", z[p], z[p+1], sum1[p+1]);
printf("The sum obtained for z between %d - %d \
\nusing the second formula is %Lf \n", z[p], z[p+1], sum2[p+1]);
}
return 0;
}
The working code without the outermost for loop is
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 1200
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int k, z = 3;
long double sum1 = 0, sum2 = 0, pro = 1.0;
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z, 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1 += summand1[k];
}
//Wolfamalpha site gives the same value here
printf("The sum obtained for z between 0-3 using the first formula is %Lf \n", sum1);
for (k = 0; k <= N; k++)
{
pro *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) * powl(z, 2 * k + 1) / pro));
//printf("%Le \n", pro);
sum2 += summand2[k];
}
sum2 = sum2 * expl((-powl(z,2)) / 2);
printf("The sum obtained for z between 0-3 using the second formula is %Lf \n", sum2);
return 0;
}
I'm quite certain that the problem is in factor not being set back to 1 in the outer loop..
factor *= (2 * k + 1); (in the loop that calculates sum2.)
In the second version provided the one that works it starts with z=3
However in the first loop since you do not clear it between iterations on p by the time you reach z[2] it already is a huge number.
EDIT: Possible help with precision..
Basically you have a huge number powl(z[p], 2 * k + 1) divided by another huge number factor. huge floating point numbers lose their precision. The way to avoid that is to perform the division as soon as possible..
Instead of first calculating powl(z[p], 2 * k + 1) and dividing by factor :
- (z[p]z[p] ... . * z[p]) / (1*3*5*...(2*k+1))`
rearrange the calculation: (z[p]/1) * (z[p]^2/3) * (z[p]^2/5) ... (z[p]^2/(2*k+1))
You can do this in sumand2 calculation and a similar trick in summand1