This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
Take this c++ code:
double d = 0.3028 + 0.0028;
cout << d << endl;
if (d == 0.3056)
cout << "match" << endl;
else
cout << "not a match" << endl;
Why is the output "not a match"?
Well that is because how floats are stored in memory. Here is a good article on this: https://dev.to/visheshpatel/how-floating-point-no-is-stored-memory-47od
Instead floats (and doubles) should be checked if are "almost equal". In your case, if you are interested only in 4 decimal places then you can check if the difference is lower than 0.00001. So:
float epsilon = 0.00001;
double a = d; //your value
double b = 0.3056; //the value to which you are comparing
bool equal_ab = abs(a - b) < epsilon;
This is the nature of finite precision math.
If you use, say, six digits of decimal precision, 1/3 will be represented as 0.333333 and if you do "3 * 1/3" you will get 0.999999, not 1.
Similarly, 2/3 will be 0.666667, so 2 * 1/3 will not give 2/3. 1/3+1/3 will give 0.666666, not 2/3.
Finite precision representations are funny this way and testing them for precise equality is generally a bad idea.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
While studying about float datatypes I wrote a program in C++:
float a = 0.3, b = 0.4, c = 0.7;
cout << "a+b= " << (a + b) << endl;
if ((a + b) == c)
{
cout << "Success..." << endl;
}
else
{
cout << "Failure..." << endl;
}
The output I received was:
a+b= 0.7
Failure...
I am using visual studio code as my IDE and it facilitates that on hovering the cursor over a declared variable it shows the approximate value assigned to the variable and I realized that for a it was 0.2999999999999999889, for b:0.4000000000000000222 and for c:0.6999999999999999556.
So, my question is that is there a method/a data type which can store the true value of a floating point.
And why does the system stores these values in approximate form rather than in the true value.
Why does the system assign approximate value to the floating point numbers
In short: Because there are infinitely many fractional numbers while the computer doesn't have infinite memory.
The compromising solution to that is to represent only some of the fractional numbers. And since computer hardware often use binary base, it just so happens that many decimal fractions such as 1/10 are not those that can be represented.
is there a method/a data type which can store the true value of a floating point.
Those values that you see true values stored in the floating point.
If you mean, is there a datatype that can represent 1/10 and the other mentioned fractions accurately, then
No, there is no such built-in type in C++
But such numbers can be represented with more complex structures. A very trivial example is to use int nominator = 1, denominator = 10. A class type can closely emulate operations of an integer type through operator overloads. This particular naïve representation is not efficient due to many values that have duplicate representations.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Floating point inaccuracy examples
double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;
result: 0.2999999999999999889
double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;
result: 15.000000000000014211
So.. 'a' is smaller than it should be.
But if we take 'a' 50 times - result will be bigger than it should be.
Why is this?
And how to get correct result in this case?
To get the correct results, don't set precision greater than available for this numeric type:
#include <iostream>
#include <limits>
int main()
{
double a = 0.3;
std::cout.precision(std::numeric_limits<double>::digits10);
std::cout << a << std::endl;
double b = 0;
for (char i = 1; i <= 50; i++) {
b = b + a;
};
std::cout.precision(std::numeric_limits<double>::digits10);
std::cout << b << std::endl;
}
Although if that loop runs for 5000 iterations instead of 50, the accumulated error will show up even with this approach -- it's just how floating-point numbers work.
Why is this?
Because floating-point numbers are stored in binary, in which 0.3 is 0.01001100110011001... repeating just like 1/3 is 0.333333... is repeating in decimal. When you write 0.3, you actually get 0.299999999999999988897769753748434595763683319091796875 (the infinite binary representation rounded to 53 significant digits).
Keep in mind that for the applications for which floating-point is designed, it's not a problem that you can't represent 0.3 exactly. Floating-point was designed to be used with:
Physical measurements, which are often measured to only 4 sig figs and never to more than 15.
Transcendental functions like logarithms and the trig functions, which are only approximated anyway.
For which binary-decimal conversions are pretty much irrelevant compared to other sources of error.
Now, if you're writing financial software, for which $0.30 means exactly $0.30, it's different. There are decimal arithmetic classes designed for this situation.
And how to get correct result in this case?
Limiting the precision to 15 significant digits is usually enough to hide the "noise" digits. Unless you actually need an exact answer, this is usually the best approach.
Computers store floating point numbers in binary, not decimal.
Many numbers that look ordinary in decimal, such as 0.3, have no exact representation of finite length in binary.
Therefore, the compiler picks the closest number that has an exact binary representation, just like you write 0.33333 for 1⁄3.
If you add many floating-point numbers, these tiny difference add up, and you get unexpected results.
It's not that it's bigger or smaller, it's just that it's physically impossible to store "0.3" as an exact value inside a binary floating point number.
The way to get the "correct" result is to not display 20 decimal places.
To get the "correct" result, try
List of Arbitrary-precision arithmetic Libraries from Wikipedia:
http://en.wikipedia.org/wiki/Arbitrary-precision
or
http://speleotrove.com/decimal
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I want to calculate the sum of three double numbers and I expect to get 1.
double a=0.0132;
double b=0.9581;
double c=0.0287;
cout << "sum= "<< a+b+c <<endl;
if (a+b+c != 1)
cout << "error" << endl;
The sum is equal to 1 but I still get the error! I also tried:
cout<< a+b+c-1
and it gives me -1.11022e-16
I could fix the problem by changing the code to
if (a+b+c-1 > 0.00001)
cout << "error" << endl;
and it works (no error). How can a negative number be greater than a positive number and why the numbers don't add up to 1?
Maybe it is something basic with summation and under/overflow but I really appreciate your help.
Thanks
Rational numbers are infinitely precise. Computers are finite.
Precision loss is a well known problem in computer programming.
The real question is, how can you remedy it?
Consider using an approximation function when comparing floats for equality.
#include <iostream>
#include <cmath>
#include <limits>
using namespace std;
template <typename T>
bool ApproximatelyEqual(const T dX, const T dY)
{
return std::abs(dX - dY) <= std::max(std::abs(dX), std::abs(dY))
* std::numeric_limits<T>::epsilon();
}
int main() {
double a=0.0132;
double b=0.9581;
double c=0.0287;
//Evaluates to true and does not print error.
if (!ApproximatelyEqual(a+b+c,1.0)) cout << "error" << endl;
}
Floating point numbers in C++ have a binary representation. This means that most numbers that can exactly represented by a decimal fraction with only a few digits cannot be exactly represented by floating point numbers. That's where your error comes from.
One example: 0.1 (decimal) is a periodic fraction in binary:
0.000110011001100110011001100...
Therefore it cannot be exactly be represented with any number of bits with binary encoding.
In order to avoid this type of error, you can use BCD (binary coded decimal) numbers which are supported by some special libraries. The drawbacks are slower calculation speed (not directly supported by the CPU) and slightly higher memory usage.
ANother option is to represent the number by a general fraction and store numerator and denomiator as separate integers.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 7 years ago.
int base = 12;
double number = 12.2112;
double c = number - base;
//// c=0.211199999999999983
this is c++ code,
How could I get the outcome: c= 0.2112,
0.2112 cannot be exactly represented in Floating Point Notation: https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
If it's extremely important to you that 0.2112 be represented exactly, then the usual solution looks a bit like this:
int base = 120000;
int number = 122112;
int c = number - base;
cout << "Value of c: " << (c / 10000.0) << endl;
Know, however, that what we're doing here is implementing fixed-point numbers. If you need fixed-point numbers in your implementation, it may be worthwhile to research and implement a full fixed-point class that does everything you're trying to accomplish here.
This question already has answers here:
Round a float to a regular grid of predefined points
(11 answers)
Closed 5 years ago.
how do i round to the second decimal point in C++.
thanks for your help.
You can multiply by 100 and then round to an integer. Then put the decimal point after the first 2 digits.
For example:
void round(double x)
{
double y = 100 * x;
int rounded = (int)(y + 0.5);
printf("%lf rounded = %d.%02d\n", x, rounded / 100, rounded % 100);
}
When printing doubles you can specify the precision:
f,F
The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
Try:
printf("%f rounded = %.2f\n", x, x);
The same thing in C++
std::cout << x << " rounded = " << std::setprecision(2) << x << "\n";
If you're expecting an exact result in a double or float, it may be impossible. Many numbers that can be exactly represented in two decimal digits can't be represented in the base 2 floating point numbers at all, and all you'll get is the nearest equivalent. For example you might find that 1.10 is stuck at 1.1000000000000001 no matter how many times you try to round it.
You didn't specify which kind of rounding you need.
Assuming rounding to the nearest integer:
#include <math.h>
#include <stdio.h>
double round(double x) { return floor(x * 100 + 0.5) / 100; }
int main()
{
printf("%g\n", round(12.345));
}
It prints 12.35.
Or if you just want to print a number rounded to two digits after decimal point:
printf("%.2f\n", x);
Check out round() for float in C++ which talks about rounding floats although not to 2 places. The same basic techniques should work.