double, float, {0.0}, {0.0f}, what's the big deal? - c++

So I wrote this small practice program that tells you how many nickels and cents you would need for the amount given. I don't undersand why the program outputs 0 for cents even the the math is correct. I can't seam to understand what the issue is.
// Example program
#include <iostream>
using namespace std;
int main()
{
const double nickels{0.05};
const double cents{0.01};
int amt_needed_nickels{0}, amt_needed_cents{0};
double amt_val{0.06f}; // for 0.06 cents
double amt_val_copy{amt_val};
amt_needed_nickels = amt_val / nickels;
if(amt_needed_nickels != 0)
amt_val -= (nickels * amt_needed_nickels);
amt_needed_cents = amt_val / cents;
cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
cout << "Even though amt_val is " << amt_val << ", and cents is also " << cents << ", and 0.01/0.01 does equal 1, why is amt_needed_cents not 1?\n";
}
To be fair I know if i change the const double cents{0.01} to const float cents{0.01}, and remove the f from double amt_val{0.06f}; to double amt_val{0.06}; it will work, but i fail to understand what's really going on beneath the surface. Why does the program give 0 to amt_needed_cents above, and 1 in the other cenario?
// Example program
#include <iostream>
using namespace std;
int main()
{
const double nickels{0.05};
const float cents{0.01};
int amt_needed_nickels{0}, amt_needed_cents{0};
double amt_val{0.06}; // for 0.06 cents
double amt_val_copy{amt_val};
amt_needed_nickels = amt_val / nickels;
if(amt_needed_nickels != 0)
amt_val -= (nickels * amt_needed_nickels);
amt_needed_cents = amt_val / cents;
cout << "If it costs $" << amt_val_copy << ", you'll need:\nNickels: " << amt_needed_nickels << "\nCents: " << amt_needed_cents << "\n";
cout << "I know this is correct, but I don't know what the compiler is thinking with this as compared to the other\n\n";
}

Floating point calculations are not precise, when doing math you get the very small difference, which will break your program if you try to check for an exact equality of the numbers. For example, 1.2 * 3 is not exactly 3.6 (note that this doesn't mean all calculations are inexact: e.g. multiplication by any power of 2 is always exact: things like 1.5 * 2 and 1.1 / 4 always give the best answer possible). This is because decimal fractions like 1/10 and 1/100 are not exactly representable in binary, which is an issue when our coins are based on 1/100 (the cent).
In your program, you should instead represent coins as an integers by converting all values to cents, then everything will work just fine. That is, you know that the largest denominator you will ever deal with is 100, so you may as well multiply everything by 100. So, nickels is going to be 5, cents is going to be 1 and all calculations will be precise.
To avoid any confusion, here's your code in integers:
int dollars = 100, nickels = 5, cents = 1;
int amt_needed_dollars = amt_val / dollars;
amt_val -= amt_needed_dollars * dollars;
int amt_needed_nickels = amt_val / nickels;
amt_val -= amt_needed_nickels * nickels;
// skipped dividing by cents, because it's '1' anyway
int amt_needed_cents = amt_val;

Float: A floating point number. It's a single-precision 32bit number. More common.
Double: Like the name it holds "double" the value of a float. It's a double-precision 64bit number. It's more precise and can hold way more decimal points.
I'm not the best with c++ but it looks like the problem is here:
int amt_needed_nickels{0}, amt_needed_cents{0};
amt_needed_nickels = amt_val / nickels;
Try changing amt_needed_cents to a float or double the parsing/rounding it later. Unlike other languages (like JS) c++ is annoying when trying to convert types like that. You are dividing two floats to an int which probably truncates the decimal.

Related

C++ multiply float by fraction

just started C++ from a MATLAB background and getting confused.
float farenheit, celcius;
cin >> farenheit;
celcius = (farenheit - 32) * (5 / 9);
cout << "Temperature (c): " << celcius;
why does multiplying by 5/9 not work as expected, but this does?:
float farenheit, celcius;
cin >> farenheit;
celcius = ((farenheit - 32) * 5) / 9);
cout << "Temperature (c): " << celcius;
Thanks!
Thanks everyone,
C++ interprets 5 and 9 as int values so 5/9 is also an int.
5/9 = 0.566 which is truncated down to 0.
To fix this, append .0 or .f to the values be interpreted as a double or float respectively.
C++ considers 5 and 9 to be integers and the division is integer division, which means 5/9 = 0 (it returns the quotient).
So use 5.0 and 9.0 if you want them to be floating points.

how to avoid the loss of precision when trying to round number? (C++)

just finished my first week of C++(using Visual Studio 2017), I wrote a program that asks the user for the amount of money and will print the number of bills and coins. it works at the beginning, but sometimes it just prints wrong number.(when the user input $1.28, it shows 1 dollar, 1 quarter and 2 pennies.)
here is my code, is there anything wrong? the algorithm or the data type?
#include<iostream>
using namespace std;
float Q = 0.25;
float D = 0.10;
float N = 0.05;
float P = 0.01;
float Dollar = 1;
float money;
float dollars, quarters, dimes, nickels, pennies;
int main() //to break money into coins.
{
cout << "how many money do u have?" << endl;
cin >> money;
dollars = (int)money;
quarters = (int)((money - dollars*Dollar)/Q);
dimes = (int)((money - dollars*Dollar - quarters*Q) / D);
nickels = (int)((money - dollars*Dollar - quarters*Q - dimes*D) / N);
pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);
cout << "$" << money << " can be break into :" << endl;
cout << dollars << " dollars. " << endl;
cout << quarters << " quarters. " << endl;
cout << dimes << " dimes. " << endl;
cout << nickels << " nickels. " << endl;
cout << pennies << " pennies. " << endl;
}
how to avoid the loss of precision when trying to round number? (C++)
When you convert from floating point to integer, the fractional part is truncated. To ensure no loss of integer precision (getting the right "whole"), add 0.5 to the result each time e.g:
quarters = static_cast<int>(((money - dollars*Dollar)/Q)+0.5);
This however doesn't work when the result is negative e.g:
50.5 - 100 = -49.5 -> +1 = -48.5 -> -48... not 49
For negatives you would want to therefore subtract 0.5.
I'd assume, that in the line
pennies = (int)((money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) / P);
the part (money - dollars*Dollar - quarters*Q - dimes*D - nickels*N) will produce a value, that is not exactly .03, but a tad below. This is due to the nature of floating point arithmetic, you should read on that. Given that it's something like .029999999995, division by .01 will not yield 3.0, but maybe 2.9999999995. Since you are not rounding, but casting the value to an integer, the whole part after the period will be thrown away, hence it results in 2 pennies.
How can you solve this issue?
The simplest thing will be to round the value instead of casting it, this should yield the correct value, but this is kind of a hacky solution to an issue there is an exact solution for. You could also try to use double instead of a float, but this, too, would not solve the issue. You might get this correct, but the same a similar bug could still occur.
Store whole pennies
You could store the whole amount as an integer (whole pennies)
int amountInPennies;
int penniesPerDollar = 100;
int penniesPerQuarter = 25;
int penniesPerDime = 10;
int penniesPerNickle = 5;
int totalDollars = amountPennies / penniesPerDollar;
int totalQuarters = (amountPennies - totalDollars * penniesPerDollar) / penniesPerQuarter;
...
Decimal types
In a real world application dealing with money (well, depending on the type) you'd most likely go with some kind of decimal type instead of a float. According to this answer there are libraries with arbitrary precisions arithmetic available under the GNU license. You could still roll your own decimal type, that - more or less - does what I presented in the first approach. This might be a great excercise to learn, but maybe a ready-made library would be the better option when it comes to a real world application.

C++ numbers aren't rounding correctly

I am new to Stack Overflow, and programming in general. I am in a few classes for programming C++ and have come across an assignment I am having a bit of trouble with. This program is supposed to take fahrenheit and convert it to celsius. I have seen other programs, but could not find a duplicate to my particular problem. This is my code.
#include <iostream>
using namespace std;
int main()
{
int fahrenheit;
cout << "Please enter Fahrenheit degrees: ";
cin >> fahrenheit;
int celsius = 5.0 / 9 * (fahrenheit - 32.0);
cout << "Celsius: " << celsius << endl;
return 0;
}
So this is working great on 4 of the 5 tests that are run. It rounds 22.22 to 22 and 4.44 to 4 like it should, but when 0 F is put in, it rounds -17.77 to -17 instead of -18. I have been researching for about an hour and would love some help! Thank you.
Use std::round() instead of relying on the implicit conversion from double to int. Either that, or do not use conversion at all, show the temperature as a double.
EDIT: As others already pointed out, implicit conversion will not round but truncate the number instead (simply cut off everything after the decimal point).
Integers round down implicitly, as do casts to integer types.
Most likely, using a float in place of an int would give the most sane results:
#include <iostream>
using namespace std;
int main()
{
int fahrenheit;
cout << "Please enter Fahrenheit degrees: ";
cin >> fahrenheit;
float celsius = 5.0 / 9 * (fahrenheit - 32.0);
cout << "Celsius: " << celsius << endl;
return 0;
}
To get normal-looking output (fixed-point like "14.25", not scientific with e notation), pass std::fixed to cout before printing the floating point. You can also use cout.precision() to set the number of digits you would like in the output.
If for some other reason you need an int, use std::round() around the right hand of the expression.
When the compiler converts a floating point number to an integer, it doesn't round, it truncates. I.e. it simply cuts of the digits after the decimal point. So your program behaves as it is programmed to do.
int x = 3.99;
int y = std::round(3.99);
std::cout
<< "x = " << x << std::endl
<< "y = " << y << std::endl
;
-->
x = 3
y = 4
C/C++ is not doing floating point round when static_cast<int>-ing a float to an int. If you want to round, you need to call library function std::round()

C++ Money Class - storing and rounding cents

thanks in advance.
I'm writing a C++ assignment for class where we're creating our own money/currency class. I'm having trouble figuring out why my passing of a float isn't giving me enough precision.
Implementation:
private:
long int DOLLARS;
short int CENTS;
Currency::Currency(float tmpMoney)
{
// cout << "tmpMoney is: " << tmpMoney << endl;
int tmpDollar;
float tmpCent;
tmpDollar = static_cast<int>(tmpMoney);
tmpCent = (tmpMoney-tmpDollar)*100;
DOLLARS = tmpDollar;
CENTS = tmpCent;
}
Main Program:
Currency c1(2342.59);
Currency c2(2342.515); // there is no half cent coin, round it to 2342.52
If I output 'tmpMoney' it just gives me (for c2) 2345.51.
I'm not sure how to round .515 if the value doesn't even go that far.
It's a bad idea to make a currency type be constructible from floating-point type.
7 decimal digits is in general beyond float precision. You can still get desired output by:
float tmpMoney = 2342.515;
cout << setprecision(7) << tmpMoney << endl;
// 2342.515
But the internal representation is far from perfect:
cout << setprecision(10) << tmpMoney << endl;
// 2342.514893
If the number is large enough, you'll lose more:
float tmpMoney = 123456789.12;
cout << setprecision(12) << tmpMoney << endl;
// 123456792
So you may decide to use double instead, but you should be really careful because for large enough numbers you'll get the same errors:
double tmpMoney = 3333333333333333.42; // 17 digits
cout << setprecision(18) << tmpMoney << endl;
// 3333333333333333.5
If there is a chance that you'll have such numbers, don't initialize Currency with double either.
I would advise you to have just a constructor like Currency(int dollars, int cents).
You can also check this question for some insights.
#include <cmath>
CENTS = round(tmpCent);
Due to floating point representation, this may not always give the right result. The closest you can get is have a margin of error epsilon, say
#define EPS 0.000001
then you can do
CENTS = round(tmpCent + EPS);
Note that this will accept values that are represented as 0.499999 <= x < 0.5
And it's preferable to use double and not float to keep the precision as close as possible.

How to +1 to the digit if the first decimal is greater than or equal to 5?

My goal is to add the value in front of my decimal place when the first decimal places is more than or equal to 5.
For example:
#include <iostream>
using namespace std;
int main()
{
float num = 0.5222f;
cout << (int)num << endl;
cin.get();
return 0;
}
My intended result is 1 instead of 0. How should I modify the code to get the expected result?
If you want to round this value to the nearest integer, you could just add 0.5 before casting it to int:
float num = 0.5222f;
cout << (int)(num + 0.5);
or alternatively you might use one of the following functions from the <cmath> header:
double round (double x);
float roundf (float x);
long double roundl (long double x);
In C++11 we now have std::round, so this would work fine:
std::cout << std::round(num) << std::endl;
would also need to include <cmath>. The non-C++11 method using floor:
std::cout << floor(num + 0.5) << std::endl;
If you cast a float to an int it rounds towards zero, dropping the fractional portion of the number.
What you want to do is call roundf first. (round for double, roundf for float)
cout << (int)roundf(num) << endl;
I just add:
float num = 0.5222f;
cout << std::floor(num + 0.5);
In this way you can even decide to round up also if (say) first digit is > 3
float num = 0.3222f;
cout << std::floor(num + 0.7);
Don't know how much useful, but.... you can!
Try the ceil function.
It rounds up numbers of 0.5 to a whole decimal number by 1.
http://en.cppreference.com/w/cpp/numeric/math/ceil