This is a small program that calculates the gaps of 'interval' size that are beetween two numbers 'from' 'to'. Then I calculate the 'size' (number of gaps) and store it in an int variable, and give me a smaller value sometimes.
Here is the code:
double from=0, to=1, interval=0.1;
cout << "WORKING WITH VARIABLES: " << endl;
double operation = (to-from)/interval +1;
cout << "Size: " << operation << endl;
int size = operation;
cout << "Size after storing: " << size << endl << endl;
cout << "WORKING WITHOUT VARIABLES: " << endl;
cout << "Size: " << (to-from)/interval +1 << endl;
size = (to-from)/interval +1;
cout << "Size after storing: " << size << endl << endl;
Problem seems to be in how it's stored interval. If interval=1 everything is good, but if is 0.1, as in the example it give me 10 instead 11 in the "Size after storing" of the second case.
I've found out that it works well with interval=0.25 (2^-2).
EDIT: I haven't found that it fails in the first case, always does in the second.
Floating point numbers are stored with a finite precision, and in binary. 0.25 is easy. That's just 1/4, so 0.01 binary. 0.1 is 1/10, which cannot be represented by a finite binary string. It's 1/16+1/32+ ...
So 1/10 is rounded down, and 10 * 1/10 is slightly less than 1.
As for the different results in the first and second case, that's probably because intermediate values are rounded to more digits than double has.
You are suffering from the inaccuracies inherent in floating point arithmetic. What you probably get in the 0.1 case is 10.999.... instead of 11. Converting double to int truncates instead of rounding so you get 10. Add a small value before converting to int to combat this.
int size=operation+0.0000000001;
If you want to convert a double that is close to an integer (due to rounding errors, as explained by others) to an int, always round the value to the nearest integer, e.g. with round(), before converting the value to int, since double to int conversion truncates the value and will yield an incorrect result if the error is negative.
Related
The following code in C++:
double x = 500000.6;
printf("%f\n", x);
cout << x << endl;
prints the following:
500000.600000
500001
Why cout isn't printing the correct value (500000.6)?
Putting the following line as the beginning of the code makes cout prints correct result:
cout.precision(7);
However, setting the precision to 6 (which is the default anyways) doesn't print the expected result.
Why this happen? I have only 1 digit after the decimal point, not 7 digits!
By default, the precision is the total number of significant digits. It's not the number of digits after the decimal point. 500000.6 has seven significant digits, 500001 has only six.
Try this instead
cout << fixed << setprecision(1) << x << endl;
When used for fixed format, the precision is the number of digits after the decimal point.
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.
When I try and round digits using setprecision(2) in C++, numbers like "0.093" re returned- THREE, not two digits after the decimal! I cannot figure out why this is. I've included my very rudimentary code below, in case I am severely missing some point. Thanks!
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double tax = 0.06 ; //Tax Rate
float cost ; //Cost of item
float computed ; //Non-rounded tax
cout << "Enter the cost of the item: " ;
cin >> cost ;
computed = tax*cost;
cout << "Computed: $" << computed << endl;
cout << "Charged: $" << setprecision(2) << computed << endl; //Computed tax rounded to 2 decimal places
return 0;
}
This is because std::setprecision doesn't set the digits after the decimal point but the significant (aka "meaningful") digits if you don't change the floating point format to use a fixed number of digits after the decimal point. To change the format, you have to put std::fixed (documentaion) into your output stream:
cout << "Charged: $" << fixed << setprecision(2) << computed << endl;
From: http://www.cplusplus.com/reference/iomanip/setprecision/
The decimal precision determines the maximum number of digits to be written on insertion operations to express floating-point values. How this is interpreted depends on whether the floatfield format flag is set to a specific notation.
...
On the default floating-point notation, the precision field specifies the maximum number of meaningful digits to display in total counting both those before and those after the decimal point.
In your case: 0.093, 93 - two meaningful digits.
cout << fixed <<setprecision(6)<< a<<endl; // add whatever you want to round in the place of a
How I can prevent rounding error in C++ or fix it?
Example:
float SomeNumber = 999.9999;
cout << SomeNumber << endl;
It prints out 1000!
You can alter the rounding done by cout by setting the precision.
cout.precision(7);
float SomeNumber = 999.9999;
cout << SomeNumber << endl;
Alternatively, you can use printf from cstdio.
By default, formatted output via std::ostream rounds floating-point values to six significant decimal figures. You need seven to avoid your number being rounded to 1000:
cout << setprecision(7) << SomeNumber << endl;
^^^^^^^^^^^^^^^
Also, be aware that you're close to the limit of the precision of float, assuming the commonly-used 32-bit IEEE representation. If you need more than seven significant figures then you'll need to switch to double. For example, the following prints 1000, no matter how much precision you specify:
float SomeNumber = 999.99999; // 8 significant figures
cout << setprecision(10) << SomeNumber << endl;
To prevent your output being rounded, use setprecision in iomanip.
float SomeNumber = 999.9999;
std::cout << SomeNumber << std::endl; //outputs 1000
std::cout << std::setprecision (7) << SomeNumber << std::endl; //outputs 999.9999
return 0;
The actual value stored in SomeNumber will always be 999.9999 though, so you don't need to worry about the value itself (unless you need more precision than float provides).
As mentioned previously, if you're looking only for cout rounding fix, use the .precision function. If you're referring to the incapacity of floating points to represent every possible fractions, read below:
You can't avoid such rounding errors using floating point numbers. You need to represent your data in a different way. For example, if you want 5 digits of precision, just store it as a long which represent the number of your smallest units.
I.e. 5.23524 w/ precision at 0.00001 can be represented in a long (or int if your range of values fit) as 523524. You know the units are 0.00001 so you can easily make it work.
I have the following :
int R=25;
double pi=3.14;
double r=R*sqrt(rand());
cout<<"r: "<<r<<endl;
double th=2*pi*rand();
cout<<"th: "<<theta<<endl;
I want to convert : r=1.98 and th=5.08. I would also like the double result=r*th to be with 2 zecimals.
when I print double result =r*th; the number is very huge and is not realistic.
How to change the r and th value to 1.98 and 5.08? How to solve this?
I need to change each double to just 2 decimals after "."
I am working in c++ under ubuntu.
Thx appreciate
To produce random values in the range you specified, try this:
r = (R*(rand()/(RAND_MAX + 1.0)));
th = (2*3.14*(rand()/(RAND_MAX + 1.0)));
The expression rand()/(RAND_MAX+1.0) produces values in the range [0,1.0). Multiplying that by the range limit gives you the numbers you want.
Note: this doesn't limit the numbers to two decimal places, which is more a function of how you print them. To print them with two decimal places, try this:
std::cout << std::fixed << std::setprecision(2) << r << "\n";
std::cout << std::fixed << std::setprecision(2) << th << "\n";
std::cout << std::fixed << std::setprecision(2) << (r*th) << "\n";
See this question: C++ generating random numbers
If you need to make both numbers smaller by the same amount then you can simply divide them both by the same number. You'll lose approximately the same precision either way.
If you really want to completely alter the result by chopping off the exponent then you could probably dig into the double number format itself and separate out the mantissa.
Why you would do this is a mystery to me.