I am writing a function for class that takes an amount of money and tells the user how many coins add up to that amount. I seem to have everything working just fine, except pennies. My loop will sometimes stop short and break before adding the proper amount. It usually will stop 1 penny short, but sometimes it will give me the proper answer (one value I have found that gives the correct answer is .09). I've tried changing the float to a double, and I have the same issue. I am pulling my hair out trying to figure out what I am doing wrong.
void change(float total)
{
int quarters, dimes, nickels, pennies;
quarters = 0;
dimes = 0;
nickels = 0;
pennies = 0;
printf("\nTotal value entered: %.2f", total);
while (total >= .25)
{
quarters += 1;
total -= .25;
}
while (total >= .10)
{
dimes += 1;
total -= .10;
}
while (total >= .05)
{
nickels += 1;
total -= .05;
}
while (total >= .01)
{
pennies += 1;
total -= .01;
}
printf("\nQuarters: %d \nDimes: %d \nNickels: %d \nPennies: %d\n\n", quarters, dimes, nickels, pennies);
}
It's almost certainly caused by the limited precision of floating point numbers.
You'll probably find that you're reaching a point where the remaining value is something like 0.009999942 rather than 0.1 and that's why you're exiting early.
But it can show itself even before you reach pennies, if you end up with something like 0.249999 left, which should be a quarter but precision limits may force down to two dimes and four pennies.
As to solving it, I'd get the floating point value rounded to an integer as quickly as possible (multiplying it by a hundred beforehand of course), then you don't have to worry about floating point precision.
You can do this with something like:
int itotal = total * 100 + 0.2;
then using itotal for your calculations:
while (itotal >= 25) {
quarters++;
itotal -= 25;
}
// and so on ...
I had a similar question a while back for one of my labs. Instead of a a while loop for each coin denominations, i had a single do..while with cascaded if statements. In my case the max cost of an item was $1, and I opted to work in ints, but you can format the final output later.
int price, remainder, quarters, dime, nickel, pennies;
printf("Enter the price of the item you bought:>");
scanf("%d", &price);
remainder = 100 - price;
do {
if (remainder >= 25)
{
quarters++;
remainder -= 25;
}
else if (remainder >= 10)
{
dime++;
remainder -= 10;
}
else if (remainder >= 5)
{
nickel ++;
remainder -=5;
}
else if (remainder >= 1)
{
pennies ++;
remainder -=1;
}
} while (remainder > 0);
printf("\nYour change will be dispensed as:\n Quarters: %d \n Dimes: %d \n Nickel: %d \n Pennies: %d \n\n", quarters, dime, nickel,pennies);
Hope it helps.
Floating point math is not exact. See http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Floating point math is very complex and subject to many common mis expectations. Try converting your math to using int, and later translate it back.
As you are comparing float which subjected to be full of errors so you can use a roundof function and change the floating point number to integer.
int_total = round( total * 100.0 ); //include math.h
Now, change the loop as,
while (total >= 25)
{
quarters += 1;
total -= 25;
}
Related
I want to convert a floating point number like 0.15 -> 15 or 0.4 -> 4
My idea is to
Multiply a number with amount of floating point places.
Floor it.
Cast it to (int).
Can't figure how to do the first step.
Clarification: I have to make a program that uses a greedy algorithm, User enters change_owed. This program would then check for the lowest number of coins possible to give-out.
Code:
#include <ctype.h>
#include <stdio.h>
int main(void)
{
int coins = 0;
float cash_owed = 0;
do
{
printf("Cash owed: ");
scanf("%f" , &cash_owed);
}
while(cash_owed < 0);
while(cash_owed > 0)
{
if(cash_owed >= 0.25)
{
cash_owed -= 0.25;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed >= 0.10)
{
cash_owed -= 0.10;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed >= 0.05)
{
cash_owed -= 0.05;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else
{
cash_owed -= 0.01;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
}
printf("%d\n", coins);
return 0;
}
Not my best design. But it fails on many different examples given below, Acc to my understanding it's due to floating-point arithmetic imprecision.
Fails for: 0.15, 1.6 and 4.2. wherein it skips one or more if statement due to floating-point arithmetic imprecision.
So I devised a new algo which will convert these values to proper int. Like
0.15 -> 15
So I have to work with integers to eliminate that float point errors, If this makes any sense
to convert a floating point number like 0.15 -> 15 or 0.4 -> 4
Recognize 0.15 and 0.4 are not exactly encodable as a floating point number as they are not dyadic as typically used: e.g. binary32. Instead a nearby value is saved in cash.
Multiply the floating point number by 100. Since the product determination may round and the original number may only be close to a few digit decimal number, round the result. Using floor may take a value of xxx.9999... to xxx.0 rather than a more reasonable xxx.0 + 1.
#include <math.h>
long cash_in_cets = lround(cash * 100.0);
Proceed with rest of greedy algorithm using integer math and integer cents,
My crystal ball hints that the next version of C will specify decimal floating point numbers, which is a great solution for money.
Code can stay with only using FP types, yet test like (cash_owed >= 0.10) are too simplistic/wrong and need significant rework. Best to move to integer math.
You don't need to convert from floating point to integer to get the program to work.
From what I could see, the problem is that your program has no idea what to do once it gets to 0, probably because it never actually reaches absolute zero. One way to get around this is to add an additional else if statement that sets cash_owed to less than 0 whenever it gets less than 0.01:
else if(cash_owed < 0.01)
{
cash_owed = -1;
}
You also need to add a condition to the existing 0.01 else if statement:
else if(cash_owed >= 0.01)
{
cash_owed -= 0.01;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
So your while loop end up looking like this:
while(cash_owed > 0)
{
if(cash_owed >= 0.25)
{
cash_owed -= 0.25;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed >= 0.10)
{
cash_owed -= 0.10;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed >= 0.05)
{
cash_owed -= 0.05;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed >= 0.01)
{
cash_owed -= 0.01;
printf("Cash owed: %f\n", cash_owed);
coins++;
printf("Coins: %d\n", coins);
}
else if(cash_owed < 0.01)
{
cash_owed = -1;
}
}
This should work as long as your user enters valid amounts (so you might want to add a check to make sure they don't add more than 2 decimals).
I just started programming, so I know this is probably a very basic error, but i've been trying to find out how to fix the logical error in my code for the greedy.c assignment from Harvard's CS50 course without success. I have looked up solutions to the problem, but they all seem to solve it in a different manner than I am trying. I have reverse engineered the other examples, and I understand them now, but I really want to know how to make my own version run well.
I am trying to get the problem done by a series of while loops, each of which subtract a certain coin value from the total owed, and adding one coin to the total coin count. To me, it seems like logically it makes sense, but when I run the program it doesn't give me the expected output. It just doesn't execute the printf statement at the bottom. I'm hoping one of you wizzes out there can give me a hand with this! Thanks for any help!
Heres my code:
#include <stdio.h>
#include <cs50.h>
int main (void)
{
printf("How much change is needed?\n");
float owed = get_float();
int coins = 0;
/*While loops subtracting one coin from change owed, and adding one to coin count*/
while (owed >= 0.25)
{
owed = owed - 0.25;
coins = coins + 1;
}
while (owed >= 0.1)
{
owed = owed - 0.1;
coins = coins + 1;
}
while (owed >= 0.05)
{
owed = owed - 0.05;
coins = coins + 1;
}
while (owed >= 0.01)
{
owed = owed - 0.01;
coins = coins + 1;
}
/*While loops done, now print value of "coins" to screen*/
if (owed == 0)
{
printf("You need %i coins\n", coins);
}
}
Edit:
So I played around with it a little more, and finished that "if" statement. It is returning error for me, so how is the value of "owed" by the end of the program not equal to 0?
#include <stdio.h>
#include <cs50.h>
int main (void)
{
printf("How much change is needed?\n");
float owed = get_float(); //Gets amount owed from user in "x.xx" format
int coins = 0; //Sets initial value of the coins paid to 0
//While loops subtracting one coin from change owed, and adding one to coin count
while (owed > 0.25)
{
owed = owed - 0.25;
coins = coins + 1;
}
while (owed > 0.1)
{
owed = owed - 0.1;
coins = coins + 1;
}
while (owed > 0.05)
{
owed = owed - 0.05;
coins = coins + 1;
}
while (owed > 0.01)
{
owed = owed - 0.01;
coins = coins + 1;
}
//While loops done, now print value of "coins" to screen
if (owed == 0)
{
printf("You need %i coins\n", coins);
}
else
{
printf("Error\n");
}
}
Edit:
So once my code was working, I started fiddling with it and overengineering. Heres the final(for now) version!
#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <time.h>
int main (void)
{
srand(time(0)); //generates random seed
float price = round(rand()%500); //generates random price between 0 and 500 cents
printf("You owe %f. How much are you paying?\n", price/100); //shows user their price between 0 and 5 dollars
printf("Dollars: ");
float paymnt = get_float()*100; //gets the amount user will pay in dollars then converts to cents
int owed = round (paymnt - price); //calculates the change owed by paymnt-price
int coins = 0; //Sets initial value of the coins paid to 0
int quarters= 0;
int dimes = 0;
int nickels = 0;
int pennies = 0;
if (owed ==0 && price >0) //If someone pays in exact
{
printf("You paid the exact amount!\n");
}
else if (owed < 0) //If someone doesn't pay enough
{
printf("You didn't give us enough money!\n");
}
else //Else(We owe them change)
{
printf("Your change is %i cents\n", owed);
//While loops subtracting one coin from change owed, and adding one to coin count
while (owed >= 25)
{
owed = owed - 25;
quarters = quarters + 1;
}
while (owed >= 10)
{
owed = owed - 10;
dimes = dimes + 1;
}
while (owed >= 5)
{
owed = owed - 5;
nickels = nickels + 1;
}
while (owed >= 1)
{
owed = owed - 1;
pennies = pennies + 1;
}
//While loops done, now print each coin and total coins needed to screen
if (owed == 0)
{
coins = quarters + dimes + nickels + pennies;
printf("You need %i coins (%i quarters, %i dimes, %i nickels, and %i pennies)\n", coins, quarters, dimes, nickels, pennies);
}
else
{
printf("Error\n");
}
}
}
You can't really compare a float point number to a integer ( 0 ) because some of the deep assembly mechanism
What you can do:
Simply do printf("You need %i coins\n", coins) without condition
Do
if (owed <= 0.001 && owed >= -0.001)
{
printf("You need %i coins\n", coins);
}
It's actually a quite common practice
Thank you everyone for your help. I ended up following Tardis' suggestion, and utilizing integers for the calculations instead. It was a success! Heres the code I ended up with:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void)
{
printf("How much change is needed?\n");
float tmp = get_float() * 100;//Gets amount owed from user in "x.xx" format
int owed = round(tmp);
int coins = 0; //Sets initial value of the coins paid to 0
//While loops subtracting one coin from change owed, and adding one to coin count
while (owed >= 25)
{
owed = owed - 25;
coins = coins + 1;
}
while (owed >= 10)
{
owed = owed - 10;
coins = coins + 1;
}
while (owed >= 5)
{
owed = owed - 5;
coins = coins + 1;
}
while (owed >= 1)
{
owed = owed - 1;
coins = coins + 1;
}
//While loops done, now print value of "coins" to screen
if (owed == 0)
{
printf("You need %i coins\n", coins);
}
else
{
printf("Error\n");
}
}
Love the feeling of finally getting a program right. Just wish I had been able to come up with this on my own:/ Nevertheless, thanks everyone for your suggestions.
I'm trying to show the decimal points after the number
#include <stdio.h>
int main() {
int weight;
int miles;
int price;
printf("Enter the packages weight \n");
scanf("%d", &weight);
printf("Enter how many miles to ship the package \n");
scanf("%d", &miles);
if(weight <= 15) {
price = 15;
}
else {
price = (15 + ((weight - 15) * .5 ));
}
if(miles % 500 == 0) {
price += (miles / 500 * 10);
}
else {
price += ((miles / 500 )* 10) + 10;
}
printf("It will cost $%d to ship an item weighing %d pounds %d miles \n", price, weight, miles);
return 0;
}
for the price = (15+((weight-15)*.5)); When I plug in the numbers outside of the console it shows the decimal places. I'm probably missing the most simple thing...
You should change the data type of the variable price to float (or double) if you wish to store some fractional part in it.
Also, since miles / 500 may create some decimal part (and miles itself can be floating-point!), it should also be made float or double.
Finally, in the printf arguments, do not forget to change the format specifier %d.
Prefer to use a floating-point data type for all the variables involved in some computation that might yield fractional numbers as it will be more comprehensible and if you wish to not see the decimal part in the output, then set the precision to 0 (%.0f).
In my code I usede the greedy algorithm in order to use the minimum amaount of coins. For example: I must return $0.41, the minimum amount of coins I can use is 4:
1 - 0,25;
1 - 0.10;
1 - 0.05;
1 - 0.01;
There are 4 types of coins: 0.25,0.10,0.05,0.01.
Here is my code:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
printf("Enter the sum, that you want to return you:");
float sum = GetFloat();
float quaters = 0.25;
float dime = 0.10;
float nickel = 0.05;
float penny = 0.01;
int count_q = 0,count_d = 0,count_n = 0,count_p = 0;
while(sum<0){
printf("Incorrect, enter the positive float number");
sum = GetFloat();
}
while(sum > 0){
if(sum - quaters >=0){
sum -=quaters;
count_q +=1;
}
else if((sum -quaters <0) && (sum -dime>=0)){
sum -= dime;
count_d +=1;
}
else if((sum - dime <0) &&(sum - nickel>=0) ){
sum -= nickel;
count_n +=1;
}
else if(sum - nickel <0){
sum -= penny;
count_p +=1;
}
}
printf("The number of quaters: %i\n",count_q);
printf("The number of dimes: %i\n",count_d);
printf("The number of nickels: %i\n",count_n);
printf("The number of pennies: %i\n",count_p);
}
This code calculates how many coins of each type of was used to return the sum. In most cases it works fine.
But sometimes, for example, when i enter the number 1.12 it gives me wrong result:
Enter the sum, that you want to return you:1.12
The number of quaters: 4
The number of dimes: 1
The number of nickels: 0
The number of pennies: 3
I think, that the problem is in last else if statement. But i don't know how can I correct it.
To my understanding, there is no bug in your code in the strictest sense, as the reasoning on which the implementation is based (a greedy algorithm) is correct. You are most likely experiencing rounding errors due to repeated subtraction, as you use float, the single-precision floating type to represent your values. Perhaps, if you change float to double in your code, the output will be as expected for your example input.
However, this only pushes the boundaries of the limitation. Perhaps it would be better to internally represent the amount of money in pennies as int.
Note that, when first confronted with the fact that floating point representations are inaccurate, I believed that the impossibility to represent some values and accumulation of rounding errors would be an issue only when you absolutely do some rocket science calculations, but would never be relevant for what I considered to be layman's calculations. However, this is not the case.
Following up on what others have said, this will probably do the job: replace the variable declarations in your existing code with the below. The computation loop doesn't need to change since you wisely used named quantities rather than hard-coded constants.
float dollars = GetFloat();
int sum = (int)(dollars*100.0 + 0.5);
int quaters = 25;
int dime = 10;
int nickel = 5;
int penny = 1;
Edit:
The changes above have to be carried through wherever input happens. For example:
while(dollars<0){ /***/
printf("Incorrect, enter the positive float number");
dollars = GetFloat(); /***/
sum = (int)(dollars*100.0 + 0.5); /***/
}
printf("%d pennies\n", sum); /* For debugging */
I added the +0.5 to round-to-nearest rather than truncating - that might fix the 1.13 and 1.14 cases. If not, I would suggest seeing what your debugger tells you. If you are still stuck after that, please by all means post another question with your latest, updated code and test cases.
I have a do-while loop:
float amount;
do
{
printf("Input dollar amount owed:\n");
amount = GetFloat();
}
while (amount <= 0);
followed by a while loop and printf:
int coins = 0;
while (amount >= 0.25);
{
amount = amount - 0.25;
coins++;
}
printf("Number of coins to use: %d\n", coins);
return 0;
but when I run and use it, the while loop doesn't run and printf doesn't print. It looks like this in my terminal, where 1 is the user input:
Input dollar amount owed: 1
How do I get the program to move onto the while loop and printf?
while (amount >= 0.25);
^ roh roh
I think what you meant was:
while (amount >= 0.25)
{
amount = amount - 0.25;
coins++;
}
while(x); is the same as while(x) { }
This just looks like a syntax error in while (amount >= 0.25); it should be while (amount >= 0.25). just have to remove the semicolon.
It seems that you want to get the number of coins for each amount entered until a negative number is entered. To do this you want to nest the while loops. The pseudo code would be:
Get amount
Check if it is greater than 0
Get number of coins and print
Repeat
And the actual code could be something like:
float amount;
printf("Input dollar amount owed:\n");
amount = GetFloat();
while( amount >= 0 )
{
int coins = 0;
while (amount >= 0.25)
{
amount -= 0.25;
coins++;
}
printf("Number of coins to use: %d\n", coins);
printf("Input dollar amount owed:\n");
amount = GetFloat();
}
return 0;
However, your "Get number of coins" is simply doing a division followed by a floor operation. So that doesn't need a loop:
int coins = (int) (amount / 0.25f); // casting to an int will truncate the float.