This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 4 years ago.
I am declaring the amount as a float. When I multiply the value by 100 and plug it into an "int" variable the value changes to 419... why is this happening?
#include <stdio.h>
#include <cs50.h>
#include <math.h>
float amount;
int cents, coins, quarters, dimes, nickels, pennies, Q, D, N, P;
int main(void){
do
{
amount = get_float("How much we talkin?\n");
}
while (amount < 0);
printf("cents = %.55f\n", amount);
cents = amount * 100;
printf("cents = %i\n", cents);
quarters = cents % 25;
Q = cents / 25;
printf("quarters = %i\n", quarters);
dimes = quarters % 10;
D = quarters / 10;
printf("dimes = %i\n", dimes);
nickels = dimes % 5;
N = dimes / 5;
printf("nickels = %i\n", nickels);
pennies = nickels % 1;
P = nickels / 1;
printf("pennies = %i\n", pennies);
coins = Q+D+N+P;
printf("%i\n", coins);
}
~/workspace/pset1/cash/ $ ./cash
How much we talkin?
4.2
cents = 4.1999998092651367187500000000000000000000000000000000000
cents = 419
quarters = 19
dimes = 9
nickels = 4
pennies = 0
22
... that link helped. Thank you!
Thank you, I resolved this issue by taking the input from the user as a float, multiplying that value by 100, then rounding to the nearest integer. The code below works, not the cleanest solution in the world.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
float amount;
int cents, coins, quarters, dimes, nickels, pennies, Q, D, N, P;
int main(void){
do
{
amount = get_float("How much we talkin?\n");
}
while (amount < 0);
// Print float input to see value is not precise
printf("amount = %.55f\n", amount);
// Multiply amount by 100, then round to nearest
cents = roundf(amount * 100);
printf("cents = %i\n", cents);
// *Quarters*
quarters = cents % 25;
Q = cents / 25;
printf("quarters = %i\n", Q);
// *Dimes*
dimes = quarters % 10;
D = quarters / 10;
printf("dimes = %i\n", D);
// *Nickels*
nickels = dimes % 5;
N = dimes / 5;
printf("nickels = %i\n", N);
// *Pennies*
pennies = nickels % 1;
P = nickels / 1;
printf("pennies = %i\n", P);
// Add up all the coins
coins = Q+D+N+P;
printf("%i\n", coins);
}
~/workspace/pset1/cash/ $ ./cash
How much we talkin?
4.2
amount = 4.1999998092651367187500000000000000000000000000000000000
cents = 420
quarters = 16
dimes = 2
nickels = 0
pennies = 0
18
To understand this issue, you need to understand how floating point numbers are stored in memory, in their binary form.
You also need to understand that C's type conversion TRUNCATES a float when converting to an integer.
The number 4.2 is stored as:
1 x 4
0 x 2
0 x 1
0 x 0.5
0 x 0.25
1 x 0.125
1 x 0.0625
0 x 0.03125
0 x 0.015625
1 x 0.0078125
1 x 0.00390625
etc
Which sums to 4.199 (and eventually approximates to 4.199999 - but NEVER 4.2)
Multiplying by 100 gives you 419.999(etc) - and truncating this gives you 419 not 420.
The solution (as you have found) is to make sure you ROUND rather than TRUNC
Related
My task is to write a program to represent an amount of money in different coins.
UPD: I'm allowed to use <stdio.h> only, modulo and division.
The output should be:
Coin Qty Balance
-------- --- ---------
365.5700
Toonies 182 1.5700
Loonies 1 0.5700
Quarters 2 0.0700
Dimes 0 0.0700
Nickels 1 0.0200
Pennies 2 0.0000
But I'm getting this:
Coin Qty Balance
-------- --- ---------
365.5700
Toonies 182 1.5700
Loonies 1 0.5700
Quarters 2 0.0600
Dimes 0 0.0600
Nickels 1 0.0100
Pennies 1 0.0000
This is my code. I cannot get the right calculations with quarters, dimes, nickels and pennies. What have I written wrong? Maybe the issue in type casting.
#include <stdio.h>
int main() {
double total = 365.5700;
int toonies, loonies, quarters, dimes, nickels, pennies;
double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = (int)total / 2;
balToonies = (int)(total * 100) % 200 / 100.0;
// Loonies
loonies = (int)balToonies / 1;
balLoonies = (int)(balToonies * 100) % 100 / 100.0;
// Quarters
quarters = (int)(balLoonies * 100) / 25;
balQuarters = (int)(balLoonies * 100) % 25 / 100.0;
// Dimes
dimes = (int)(balQuarters * 100) / 10;
balDimes = (int)(balQuarters * 100) % 10 / 100.0;
// Nickels
nickels = (int)(balDimes * 100) / 5;
balNickels = (int)(balDimes * 100) % 5 / 100.0;
// Pennies
pennies = (int)(balNickels * 100) / 1;
balPennines = (int)(balNickels * 100) % 1 / 100.0;
printf("Coin Qty Balance\n");
printf("-------- --- ---------\n");
printf("%22.4lf\n", total);
printf("Toonies %3d %9.4lf\n", toonies, balToonies);
printf("Loonies %3d %9.4lf\n", loonies, balLoonies);
printf("Quarters %3d %9.4lf\n", quarters, balQuarters);
printf("Dimes %3d %9.4lf\n", dimes, balDimes);
printf("Nickels %3d %9.4lf\n", nickels, balNickels);
printf("Pennies %3d %9.4lf\n\n", pennies, balPennines);
return 0;
}
What have I written wrong?
Wrong use of floating point (FP) and integer math by not considering the roundings of FP math and integer truncation and their limitations of representable values.
When a FP result is just under a whole number, like x.99999..., applying (int) results in x instead of the desired x + 1.
double cannot represent values like 365.5700 exactly. Instead a nearby value is used: 365.56999999999999317878973670303821563720703125. That is a whole number * some_power_of_2.
double * 100 often results in a rounded product.
These roundings and OP's casts which truncate result in various off-by-one calculations as compared to the desired result.
Alternative today
A simple alternative is to scale the money by the smallest unit, (which appears to be Can$0.0001 in this case) and use integer math.
Let's go with a wider type than int, so code can handle small accounts as well as large ones.
#include <math.h>
typedef long long ssymoney;
#define SSYMONEY_SCALE 10000
#define SSYMONEY_FROM_double(d) llround((d) * SSYMONEY_SCALE)
#define SSYMONEY_TO_double(m) ((double)(m) / SSYMONEY_SCALE)
#define SSYMONEY_TOONIE (SSYMONEY_SCALE * 2)
#define SSYMONEY_LOONIE (SSYMONEY_SCALE * 1)
#define SSYMONEY_QUARTER (SSYMONEY_SCALE * 25 / 100)
#define SSYMONEY_DIME (SSYMONEY_SCALE * 10 / 100)
...
int main(void) {
double total = 365.5700;
ssymoney ssytotal = SSYMONEY_FROM_double(total);
long long toonies, loonies, quarters, dimes, nickels, pennies;
ssy_money balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = ssytotal / SSYMONEY_TOONIE;
balToonies = ssytotal % SSYMONEY_TOONIE ;
// Loonies
loonies = balToonies / SSYMONEY_LOONIE;
balLoonies = balToonies % SSYMONEY_LOONIE ;
// quantity = balance / denomination
// money balance_new = balance % denomination
...
printf("%22.4lf\n", SSYMONEY_TO_double(ssytotal));
printf("Toonies %3lld %9.4lf\n", toonies, SSYMONEY_TO_double(balToonies));
printf("Loonies %3lld %9.4lf\n", loonies, SSYMONEY_TO_double(balLoonies));
...
Alternative later
The next version of C may support decimal floating point. Use that for money.
You can 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/3KKbfzh4z
Thank you guys for your help! I have learned a lot. When I made this post I should have mentioned that I'm allowed only <stdio.h> library and no functions.
I came up with this solution. Please let me know what do you think.
#include <stdio.h>
int main() {
double total = 365.5700;
int toonies, loonies, quarters, dimes, nickels, pennies;
double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
// Toonies
toonies = (int)total / 2;
balToonies = (int)(total * 100 + 0.5) % 200 / 100.0;
// Loonies
loonies = (int)balToonies / 1;
balLoonies = (int)(balToonies * 100 + 0.5) % 100 / 100.0;
// Quarters
quarters = (int)(balLoonies * 100) / 25;
balQuarters = (int)(balLoonies * 100 + 0.5) % 25 / 100.0;
// Dimes
dimes = (int)(balQuarters * 100) / 10;
balDimes = (int)(balQuarters * 100 + 0.5) % 10 / 100.0;
// Nickels
nickels = (int)(balDimes * 100) / 5;
balNickels = (int)(balDimes * 100 + 0.5) % 5 / 100.0;
// Pennies
pennies = (int)(balNickels * 100);
balPennines = (int)(balNickels * 100 + 0.5) % 1 / 100.0;
printf("Sales INCLUDING tax\n");
printf("Coin Qty Balance\n");
printf("-------- --- ---------\n");
printf("%22.4lf\n", total);
printf("Toonies %3d %9.4lf\n", toonies, balToonies);
printf("Loonies %3d %9.4lf\n", loonies, balLoonies);
printf("Quarters %3d %9.4lf\n", quarters, balQuarters);
printf("Dimes %3d %9.4lf\n", dimes, balDimes);
printf("Nickels %3d %9.4lf\n", nickels, balNickels);
printf("Pennies %3d %9.4lf\n\n", pennies, balPennines);
return 0;
}
I am not quite sure how to fix the program to make it display the change someone has correctly. I will list the expected outputs and the actual outputs below, as well as the code that I have written thus far. Any help is greatly appreciated, as I am very unsure about how to go about completing this project.
Expected output for input "4.67":
Dollar Bills: 4
Quarters: 2
Dime: 1
Nickel: 1
Pennies: 2
Actual output:
Dollar Bills: 223187040
Cents Leftover
Quarters: 0
Dimes: 0
Nickels: 0
Pennies: 0
#include <stdio.h>
double user_change(double);
void user_cents(int cents);
int main() {
double user_amt, cents;
printf("Hello User!\n\nHow much money would you like change for?\nEnter any amount: $");
scanf("%lf", &user_amt);
user_change(user_amt);
user_cents(cents);
return 0;
}
double user_change (double user_amt)
{
int updated_amt = (int) user_amt;
int hundreds, fifties, tens, fives, dollar_bills;
double cents = user_amt - updated_amt;
hundreds = updated_amt / 100;
updated_amt %= 100;
fifties = updated_amt / 50;
updated_amt %= 50;
tens = updated_amt / 10;
updated_amt %= 10;
fives = updated_amt / 5;
updated_amt %= 5;
dollar_bills = updated_amt / 100;
updated_amt %= 100;
printf("\nDollar Bills: %d\n", dollar_bills);
}
void user_cents(int cents)
{
int balance = cents * 10;
int quarters, dimes, nickels, pennies;
quarters = balance / 25;
balance %= 25;
dimes = balance / 10;
balance %= 10;
nickels = balance / 5;
balance %= 5;
pennies = balance / 1;
balance %= 1;
printf("\nCents Leftover\nQuarters: %d\nDimes: %d\nNickels: %d\nPennies: %d\n", quarters, dimes, nickels, pennies);
}
This question already has answers here:
Is floating point math broken?
(31 answers)
Why not use Double or Float to represent currency?
(16 answers)
How to represent currency or money in C
(5 answers)
How to read and store currency values in C [duplicate]
Closed 2 years ago.
As a part of the CS50 course we're tasked to create a program (in C) that calculates the least amount of coins ($0.25, $0.10, $0.05 and $0.01) from a value submitted by the user.
My idea was to take the input value and multiply by 100 and use integers since the only value of interest is the number of coins and not the monetary value, hence I don't have to tinker with any decimals.
The code is:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
//If it's NOT a positive number, do this.
float n;
do
{
n = get_float("Change owed: \n");
}
while (n <= 0);
//Multiplying change owed with 100 to avoid having to deal with decimals.
int cash = n * 100;
//Calculating the number of quarters ($0.25).
int quarters = cash / 25; //How many full quarters per cash.
int quarters_rem = cash % 25; //The remainder after full amout of quarters in cash.
printf("Number of quarters: %i\n", quarters); //Test how many quarters.
printf("Remainder: %i\n", quarters_rem); //Test how much remainder.
//Calculating the number of dimes ($0.10).
int dimes = quarters_rem / 10; //How many full dimes from the remainder when all quarters are deducted.
int dimes_rem = round(quarters_rem % 10); //The remainder after full amount of dimes in quarters_rem.
printf("Number of dimes: %i\n", dimes); //Test how many dimes.
printf("Remainder: %i\n", dimes_rem); //Test how much remainder.
//Calculating the number of nickels ($0.05).
int nickels = dimes_rem / 5; //How many full nickels from the remainder when all dimes are deducted.
int nickels_rem = round(dimes_rem % 5); //The remainder after full amount of nickels in dimes_rem.
printf("Number of nickels: %i\n", nickels); //Test how many nickels.
printf("Remainder: %i\n", nickels_rem); //Test how much remainder.
//Calculating the number of cents ($0.01).
int cents = nickels_rem; //How many full cents from the remainder when all nickels are deducted.
printf("Number of cents: %i\n", cents); //Test how many nickels.
//Prints the least number of coins to be returned.
int coins = quarters + dimes + nickels + cents;
printf("%i\n", coins);
}
The thing is that when I run the code and enter 2.2, 6.2 or 8.2, the output gives me a remainder of 20 after calculating the quarters. 2.2 x 100 = 220 -> 25 x 8 = 200 which gives a remainder of 20, as expected. This is true for 2.2, 6.2, 8.2, 10.2, 12.2, 14.2 and so on.
However, this is not! true if I enter 4.2! If I enter 4.2 I expect: 4.2 x 100 = 420 -> 25 x 16 = 400 which ought to give me a remainder of 20, but instead I get a remainder of 19? I don't understand why the remainder is 19 in this instance but 20 in the others?
Typical implementation of floating-point stores numbers in binary format, so it cannot precisely store some of decimal numbers.
With this program
#include <stdio.h>
int main(void) {
float x = 4.2;
float y = x * 100;
printf("%.10f\n", y);
return 0;
}
I got output:
419.9999694824
This shows that 4.2f * 100 became slightly smaller than 420 and converting that to int will result in 419 instead of 420.
To avoid this, you should add smaller value before converting float to int in this case.
int cash = n * 100 + 0.1;
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
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
if some customer is owed 41¢, the biggest first bite that can be taken is 25¢
41 - 25 = 16
another 25¢ bite would be too big
cashier would move on to a bite of size 10¢, leaving him or her with a 6¢ problem
At that point the cashier calls for one 5¢ bite followed by one 1¢ bite
#include <cs50.h>
#include <stdio.h>
int main(void)
{
float f = get_float("Enter Cash: ");
int q;
int d;
int n;
int p;
float quarter = 0.25;
float dimes = 0.10;
float nickels = 0.05;
float pennies = 0.01;
while ( f != 0)
{
if (f >= quarter){
f = f - quarter;
q = q + 1;
} else if (f >= dimes && f < quarter) {
f = f - dimes;
d = d + 1;
} else if (f >= nickels && f < dimes) {
f = f - nickels;
n = n + 1;
} else {
f = f - pennies;
p = p + 1;
}
printf ("Quarter: %d \n Dimes %d \n Nickels %d \n Pennies %d \n", q,
d, n, p);
}
}
$ ./cash
Enter Cash: 6
Quarter: 32768
Dimes -1230737968
Nickels 0
Pennies 4205168
Quarter: 32769
Dimes -1230737968
Nickels 0
Pennies 4205168
Quarter: 32770
Dimes -1230737968
Nickels 0
Pennies 4205168
Quarter: 32771
Dimes -1230737968
Nickels 0
Pennies 4205168
Quarter: 32772
you need to initialize your variables
int q = 0;
int d = 0;
int n = 0;
int p = 0;
otherwise they have unpredictable values
I am trying to write a program to calculate change, but it doesn't seem to work.
I think that the problem is the owed 1/ paid 1; when I tried to print there values I got nothing (0).
Any help ?
#include <stdio.h>
int main()
{
double owed, paid;
int dollars, quarters, dimes, nickels, cents, remainder, owed1, paid1;
printf("how much did the customer have to pay ?\n");
scanf("%f",&owed);
printf("how much did the customer pay ?\n");
scanf("%f",&paid);
owed1 = owed * 100;
paid1 = paid * 100;
int change = paid1 - owed1;
dollars = change / 100;
remainder = change % 100;
quarters = remainder / 25;
remainder = remainder % 25;
dimes = remainder / 10;
remainder = remainder % 10;
nickels = remainder / 5;
remainder = remainder % 5;
cents = remainder;
printf("%d",dollars);
printf("Dollars:%d, Quarters:%d, Dimes:%d, Nickels:%d, Cents:%d", dollars , quarters , dimes , nickels , cents );
return 0;
}
You're using %f in your scanf, which is the format specifier for a float, but your variables are doubles. You should use %lf instead:
scanf("%lf",&owed);
Same thing for paid. You should be getting warning from your compiler about that.