I am trying to do a greedy algorithm for CS50, but for some reason I keep getting errors saying "expression result unused" when trying to divide the total sum of cents by 25, 10, 5, etc. Would someone be able to pinpoint where I am going wrong? Thank you so much in advance.
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
float Change;
int quarters = 25;
int dimes = 10;
int nickels = 5;
int pennies = 1;
int count = 0;
do
{
Change = get_float("Change: ");
}
while (Change < 0);
int cents = round(Change * 100);
while (cents % 25 >= 25)
{
cents/25;
count = count + 1;
}
while (cents % 10 >= 10)
{
cents/10;
count = count + 1;
}
while (cents % 5 >= 5)
{
cents/5;
count = count + 1;
}
while (cents % 1 >= 1)
{
cents/1;
count = count + 1;
}
printf("%d coins", count);
}
Wrong compare
The following is never true. cents % 25, the remainder after division, is always less than 25.
while (cents % 25 >= 25)
Useless code
The below divides by 25 then discards the quotient. #Some programmer dude
cents/25;
Instead in the 25, 10, 5, 1 places
// while (cents % 25 >= 25)
while (cents >= 25)
// cents/25;
cents -= 25;
More efficient code possible. Hint: while loops not needed.
Good to convert input to integers.
Deeper:
int cents = round(Change * 100); produces a float product from Change * 100, then converts to double in calling round(double). Lastly it converts the results to int as part of the assignment.
Could have used roundf(float) and skip the double conversion.
For learner code this is a good start. Note that Change * 100 can causes a rounding error which would show itself in select cases near a half cent. Suggest round(Change * 100.0)
Perhaps use long lround(double x) to expiate the final conversion from double to an integer.
Note that excessively large input causes overflow and undefined behavior.
Just as the error message is telling you: The value you are calculating cents/n isn't going anywhere. I think you are trying to do cents = cents/n.
Also, yourwhile loops are checking the value of cents but you are incrementing the variable count. So you will never exit the loop.
Related
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]);
}
EDIT: After re-writing my code in my IDE, for the 8th time today, I have made rookie mistake of giving my inputs a false data type, that has been fixed but my outputs still are incorrect.
Details about my goal: When making change, odds are you want to minimize the number of coins you’re dispensing for each customer.
Well, suppose that a cashier owes a customer some change and in that cashier’s drawer are quarters (25¢), dimes (10¢), nickels (5¢), and pennies (1¢). The problem to be solved is to decide which coins and how many of each to hand to the customer.
Expected Result:
Change owed: 0.41
4
Actual result:
Change owed: 0.41
3
#include <math.h>
#include <cs50.h>
#include <stdio.h>
int main (void)
{
float dollars;
int changeowed = 0;
do
{
dollars = get_float ("Change owed: ");
}
while (dollars < 0);
float cents = round(dollars * 100);
while (cents >= 25)
{
cents = cents - 25;
changeowed++;
}
while (cents > 10)
{
cents = cents - 10;
changeowed++;
}
while (cents > 5)
{
cents = cents - 5;
changeowed++;
}
while (cents > 1)
{
cents = cents - 1;
changeowed++;
}
printf("%i \n", changeowed);
}
Here's the problem: There are 4 loops, one for quarters, one for dimes, one for nickels, and one for pennies. The first loop condition is correct:
while (cents >= 25)
The other three are incorrect:
while (cents > 10)
while (cents > 5)
while (cents > 1)
These all need to be changed to use >= in place of >.
you can do it much simple for any nominals. 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/WdYxxr
I need to create a greedy calculator that accepts only .25, .10, .5 and .1.
I need to print the minimum amount of coins needed to fulfil the change.
This is going on a loop and I can't see what to do to fix it.
I am still learning, go easy on me :)
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
int coins = 0;
int change;
int i;
do {
change = get_float("How much change? ");
}
while (change <= 0); /* condition for acceptance*/
int cents = round(change * 100);
if (cents > 0) { /* run all whiles we get to 1c*/
while ((cents - 25) >= 25) { /* run 25c */
coins += 1;
}
while ((cents - 10) >= 10) { /* run 10c*/
coins += 1;
}
while ((cents - 5) >= 5) { /* run 5c*/
coins += 1;
}
while ((cents - 1) >= 1) { /* run 1c*/
coins += 1;
}
} else {
printf("%d", coins);
}
}
There are multiple problems in your code:
change is defined as an int, so the amount entered by the user is truncated before the computation even starts, producing an incorrect result.
you do not update cents in any of the loops, so you get an infinite loop if any of these conditions is true.
note that the conditions are incorrect: (cents - 25) >= 25 is true if cents is greater or equal to 50.
the test if (cents > 0) is incorrect. You would only print the number of coins if cents <= 0.
the last loop is useless, the number of remaining cents is the number of pennies to count.
Here is a modified version:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
float change;
do {
change = get_float("How much change? ");
}
while (change <= 0); /* condition for acceptance*/
int cents = round(change * 100); /* avoid rounding issues */
int coins = 0;
while (cents >= 25) { /* count quarters */
cents -= 25;
coins += 1;
}
while (cents >= 10) { /* count dimes */
cents -= 10;
coins += 1;
}
while (cents >= 5) { /* count nickels */
cents -= 5;
coins += 1;
}
count += cents; /* count pennies */
printf("%d\n", coins);
return 0;
}
The cents variable never changes. (cents - 25) indeed returns the value of current cents minus 25, but you don't assign it to cents variable, so one of those 4 while loops will always be true.
There is also another probem: get_float function returns float while change variable is int, if the user were to enter a value less than 1, such as .5, it would be casted to 0 and prompt again and again until the user enters a value greater than 1. Also note you would probably get a wrong answer for any non-integer input.
#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.
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