As in this question is said, there is some differences between negative and positive zero in floating point numbers. I know it's because of some important reasons. what I want to know is a short code to avoid negative zero in output.
for example in the following code:
cout << fixed << setprecision(3);
cout << (-0.0001) << endl;
"-0.000" is printed. but I want "0.000".
Note all other negative numbers (e.g. -0.001) should still be printed with the minus sign preceding them, so simply * -1 will not work.
Try depending on your precision.
cout << ((abs(ans) < 0.0005)? 0.000: ans) << endl;
How about:
cout << (value == 0.0 ? abs(value) : value) << endl;
If you care about arbitrary precision, as opposed to just a fixed one at 3, you'll need a small bit of work. Basically, you'll have to do a pre-check before the cout to see if the number will get formatted in a way you don't like.
You need to find the order of magnitude of the number to see if it the imprecise digits will be lost, leaving only the sign bit.
You can do this using the base 10 logarithm of the absolute value of the number. If negative of result is greater than the precision you have set, the number will show in a way you don't want.
log10 of 0.0001 is -4.
negative of (-4) is 4.
4 > 3 (the arbitrary precision)
Thus the value will show up unhappily.
In very bad pseudocode:
float iHateNegativeZeros(float theFloat, int precision)
{
if((theFloat < 0.0f) &&
(-log10(abs(theFloat)) > precision))
{
return -theFloat;
}
else
{
return theFloat;
}
}
Related
Following code (in c++) works fine for value less than 6 digit but it start to lose precision when dividing more than 6 digits. Code:
double number;
cin>>number;
double result = number / 2.0L;
cout<<result<<endl;
Above code gives 61729.5 for 123459 which is correct. But for 1234569 it outputs 617284 which is wrong.
Can anyone please explain what's happening here.
Thanks.
Your issue is a display issue, increase precision with std::setprecision (the default precision, as established by std::basic_ios::init, is 6):
std::cout << std::setprecision(10) << result << std::endl;
Demo
This question already has answers here:
Compare double to zero using epsilon
(12 answers)
Closed 8 years ago.
I know there are loads of topics about this question, but none of those helped me. I am trying to find the root of a function by testing every number in a range of -10 to 10 with two decimal places. I know it maybe isn't the best way, but I am a beginner and just want to try this out. Somehow the loop does not work, as I am always getting -10 as an output.
Anyway, that is my code:
#include <iostream>
using namespace std;
double calc (double m,double n)
{
double x;
for (x=-10;x<10 && m*x+n==0; x+=0.01)
{
cout << x << endl;
}
return x;
}
int main()
{
double m, n, x;
cout << "......\n";
cin >> m; // gradient
cout << "........\n";
cin >> n; // y-intercept
x=calc(m,n); // using function to calculate
cout << ".......... " << x<< endl; //output solution
cout << "..............\n"; // Nothing of importance
return 0;
}
You are testing the conjunction of two conditions in your loop condition.
for (x=-10;x<10 && m*x+n==0; x+=0.01
For many inputs, the second condition will not be true, so the loop will terminate before the first iteration, causing a return value of -10.
What you want is probably closer to something closer to the following. We need to test whether the absolute value is smaller than some EPSILON for two reasons. One, double is not precise. Two, you are doing an approximate solution anyways, so you would not expect an exact answer unless you happened to get lucky.
#define EPSILON 1E-2
double calc (double m,double n)
{
double x;
for (x=-10;x<10; x+=0.001)
{
if (abs(m*x+n) < EPSILON) return x;
}
// return a value outside the range to indicate that we failed to find a
// solution within range.
return -20;
}
Update: At the request of the OP, I will be more specific about what problem EPSILON solves.
double is not precise. In a computer, floating point number are usually represented by a fixed number of bits, with the bit representation usually being specified by a standard such as IEE 754. Because the number of bits is fixed and finite, you cannot represent arbitrary precision numbers. Let us consider an example in base 10 for ease of understanding, although you should understand that computers experience a similar problem in base 2.
If m = 1/3, x = 3, and n = -1, we would expect that m*x + n == 0. However, because 1/3 is the repeated decimal 0.33333... and we can only represent a fixed number of them, the result of 3*0.33333 is actually 0.999999, which is not equal to 1. Therefore, m*x + n != 0, and our check will fail. Thus, instead of checking for equality with zero, we must check whether the result is sufficiently close to zero, by comparing its absolute value with a small number we call EPSILON. As one of the comments pointed out the correct value of EPSILON for this particular purpose is std::numeric_limits::epsilon, but the second issue requires a larger EPSILON.
You are are only doing an approximate solution anyways. Since you are checking the values of x at finitely small increments, there is a strong possibility that you will simply step over the root without ever landing on it exactly. Consider the equation 10000x + 1 = 0. The correct solution is -0.0001, but if you are taking steps of 0.001, you will never actually try the value x = -0.0001, so you could not possibly find the correct solution. For linear functions, we would expect that values of x close to -0.0001, such as x = 0, will get us reasonably close to the correct solution, so we use EPSILON as a fudge factor to work around the lack of precision in our method.
m*x+n==0 condition returns false, thus the loop doesn't start.
You should change it to m*x+n!=0
I have a program and I'm trying to calculatecos(M_PI*3/2) and instead of getting 0, as I should, I get -1.83691e-016
What am I missing here? I am in radians as I need to be.
First, M_PI is not a very portable macro and is usually good to about 15 decimal places, depending on the compiler you use - my guess is you're using Microsoft's C++ compiler.
Second, if you want a more accurate (and portable) version, use the Boost Math library:
http://www.boost.org/doc/libs/1_55_0/libs/math/doc/html/math_toolkit/tutorial/non_templ.html
Third, as Kay has pointed out, pi in itself is an irrational number and therefore no amount of bits (or digits in base 10) would be enough to accurately represent it. Therefore, What you're actually calculating is not cos(3*pi/2) exactly, but "the cosine of 3/2 times the closest approximation of pi given the bits required", which will NOT be 3 *pi/2 and therefore won't be zero.
Finally, if you want custom precision for your mathematical constants, read this: http://www.boost.org/doc/libs/1_55_0/libs/math/doc/html/math_toolkit/tutorial/user_def.html
The number M_PI is only an approximation of π. The cosine that you get back is also an approximation, and it's a pretty good one - it has fifteen correct digits after the decimal point.
Given the discrete nature of double values, the standard margin of error against which to test for numerical equality is numeric_limits<double>::epsilon():
#include <iostream>
#include <limits>
#include <cmath>
using namespace std;
int main()
{
double x = cos(M_PI*3/2);
cout << "x = << " << x << endl;
cout << "numeric_limits<double>::epsilon() = "
<< numeric_limits<double>::epsilon() << endl;
cout << "Is x sufficiently close to 0? "
<< (abs(x) < numeric_limits<double>::epsilon() ? "yes" : "no") << endl;
return 0;
}
Output:
x = << -1.83697e-16
numeric_limits<double>::epsilon() = 2.22045e-16
Is x sufficiently close to 0? yes
As you can see, the absolute value of -1.83697e-16 is within the margin of error given by epsilon 2.22045e-16.
Pi is irrational, the computer cannot represent the number perfectly. The small error to the "correct" value of pi causes the error in the output. Being 1.83691 × 10-16 off is still pretty good.
If you want to learn more about the restrictions of actual system and the impact of little errors in the input, then refer to http://en.wikipedia.org/wiki/Numerical_stability.
I want to print only one digit after the decimal dot.
So I write:
double number1 = -0.049453;
double number2 = -0.05000;
cout.setf(ios::fixed,ios::floatfield);
cout.precision(1);
cout << number1 << endl;
cout << number2 << endl;
My output is:
-0.0
-0.1
I want that the first line will be 0.0 (cause -0.0 is 0.0). How should I change my code that in a case of -0.0, it will print 0.0?
And about the second line, why doesn't it print 0.0 (or -0.0)?
Any help appreciated!
To print floating point numbers, they are rounded up if they are greater or equal to the "middle" of two possible outputs, so -0.05 becomes -0.0 intentionally.
Negative zero is the result if a negative number is rounded up to zero, also intentionally. The internal floating point format (IEEE 754) distinguishes between negative and positive zero (see this link), and it seems like C++ output streams stick to this behavior.
You can overcome both problems by separating printing the sign and the absolute value of the floating point number.
cout << (number <= -.05 ? "-" : "") << abs(number);
Explanation of the comparison: For numbers equal to or smaller than -0.05, rounding abs(number) (which is then >= 0.05) will be non-zero, so only then you want the sign to appear.
Note that the threshold value in this comparison depends on the output format you chose. So you should keep this printing method as local as possible in your code, where you know the exact format you want to print floating pointers.
Live example
Note: float and double behave exactly the same regarding these points.
I am unable to understand why C++ division behaves the way it does. I have a simple program which divides 1 by 10 (using VS 2003)
double dResult = 0.0;
dResult = 1.0/10.0;
I expect dResult to be 0.1, However i get 0.10000000000000001
Why do i get this value, whats the problem with internal representation of double/float
How can i get the correct value?
Thanks.
Because all most modern processors use binary floating-point, which cannot exactly represent 0.1 (there is no way to represent 0.1 as m * 2^e with integer m and e).
If you want to see the "correct value", you can print it out with e.g.:
printf("%.1f\n", dResult);
Double and float are not identical to real numbers, it is because there are infinite values for real numbers, but only finite number of bits to represent them in double/float.
You can further read: what every computer scientist should know about floating point arithmetics
The ubiquitous IEEE754 floating point format expresses floating point numbers in scientific notation base 2, with a finite mantissa. Since a fraction like 1/5 (and hence 1/10) does not have a presentation with finitely many digits in binary scientific notation, you cannot represent the value 0.1 exactly. More generally, the only values that can be represented exactly are those that fit precisely into binary scientific notation with a mantissa of a few (e.g. 24 or 53 or 64) binary digits, and a suitably small exponent.
Working with integers, floats, and doubles could be tricky. Depends on what is your purpose. If you only want to display in nice format, then you can play with the C++ iomanipulator, precision, showpint, noshowpint. If you are trying to do precise computing with numeric methods, you may have to use some library for accurate representation. If you are multiplying a lots of small and large number, you may have to resole to use log transformations. Here is a small test:
float x=1.0000001;
cout << x << endl;
float y=9.9999999999999;
cout << "using default io format " << y/x << endl;
cout << showpoint << "using showpoint " << y/x << endl;
y=9.9999;
cout << "fewer 9 default C++ " << y/x << endl;
cout << showpoint << "fewer 9 showpoint" << y/x << endl;
1
using default io format 10
using showpoint 10.0000
fewer 9 default C++ 9.99990
fewer 9 showpoint9.99990
In special cases you want to use double (which may be the result of some complicated algorithm) to represent integer numbers, you have to figure out the proper conversion method. Once I had a situation where I want to use a single double value to store two type of values: -1, +1, or (0-1) to make my code more memory efficient (and speed, large memory tends to reduce performance). It is a little tricky to distinguish between +1 and val < 1. In this case I know that the values < 1 has a resolution say only 1/500, Then I can safely use floor(val+0.000001) to get back the 1 value that I initially stored.