How can i avoid -0.0 in computation - c++

two double values .
double a=-324.000000
double b= 0.000000
if(a*b<0)
{
//number is less than 0
}
else
{
//number is greater than zero
}
It always gives an output as 'number less than zero'.When i multiply both of them i get the result as `-0.000000 .However the result should be 0.000000 .

This is not the result that I get. Are you sure the problem isn't somewhere else?
You said in a comment "i tried if(a==0.0){/*but it never enters here!!*/ }." It really looks like the number is not actually 0.

Consider this code:
#include<iostream>
int main() {
double a=-324;
double b= 0;
double c = a * b;
std::cout<<std::boolalpha
<<"a : "<<a<<std::endl
<<"b : "<<b<<std::endl
<<"c : "<<c<<std::endl
<<"c < 0 : "<<(c < 0)<<std::endl
<<"c > 0 : "<<(c > 0)<<std::endl
<<"c == 0: "<<(c == 0)<<std::endl
;
}
With output:
a : -324
b : 0
c : -0
c < 0 : false
c > 0 : false
c == 0: true
According to the IEEE Standard for Floating Point Arithmetic (also known as IEEE 754):
Comparisons shall ignore the sign of zero (so +0 = -0)
(quote from Section 5.11)
Your problem is somewhere else.

Yes, it is possible to generate a value of -0.0. It does compare equal to positive 0.0 so you can do the following:
double c = a * b;
if (c == 0.0)
c = 0.0;
I've actually used this code in Visual Studio to fix a formatting bug. Make sure you comment it thoroughly so people don't think you're nuts.

Related

How to get rid of -0 in C++

I am writing a program in which there are some operations being performed on a floating point number. After I debugged the program, I came to know that for a particular test case, the value of the variable equals -2.38418579e-07. Now I have cout precision set to 2 digits after decimal. So when I print it, it prints it as -0.00.
However, I would like the output to be 0.00 instead of -0.00. I have tried various if conditions on the variable's value. However, they do not help. Can anyone suggest how to get rid of -0.00 in C++
Firstly, you should define a tolerance number as threshold, where the absolute value of any floating point number bellow this threshold would be considered as zero. For example you could define this threshold as:
#define zero 1e-6
Then you could use the following construct to "filter" your floating point numbers:
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, T> sanitize(T &&num) {
return std::abs(num) < zero? T{} : num;
}
Live Demo
Notice that I use SFINAE in order for the sanitize function to accepts as input only floating point numbers.
I would like the output to be 0.00 instead of -0.00
I like the other answers better. But in a crunch you can always use brute force ... (are you sure you can ignore the actual results?)
std::string rslt;
{
std::stringstream ss;
ss << variable; // use same formatting as in your example
size_t minusSignIndx = ss.str().find("-0.00");
if (minusSignIndx != std::string::npos)
rslt = " 0.00"; // found the nasty, ignore it
else
rslt = ss.str(); // not nasty, use it
}
//... use rslt
The problem is that every floating point in a certain interval [ low , -0.0] will be printed "-0.00".
Thus you have to find low:
such that print(predecessor(low)) => "-0.01"
such that print(low) => "-0.00"
Then, you'll be able to write something like (nan apart...)
double filter(double x) {
double low = ... ;
return (x < low)
? x
: ((x > 0.0)
? x
: 0.0) ;
}
If you have a correctly rounded printf, and manage your arithmetic to be strictly IEEE754 conformant with appropriate compiler flags, the exact value of low is the nearest double to -1/200, greater than -1/200 (I write 1/200 rather than -0.005 because I'm speaking of the decimal value, not the double)
What we have with correctly rounded sscanf("-0.005","%lf",d): the double result is smaller than -1/200. I did check that with exact arithmetic like for example found in Pharo Smalltalk language:
[-0.005 < (-1/200) and: [-0.005 successor > (-1/200)]] assert.
Its successor is greater than -1/200 (necessarily, above check is just foolproofing).
Thus you can write (notice the <= low):
double filter(double x) {
double low = 0.005 ;
return (x <= low)
? x
: ((x > 0.0)
? x
: 0.0) ;
}

Can a double be greater than itself?

I know that the operator == can return false on two double (or float) values with the same content, cf c++ comparison of two double values not working properly, but can the greater than operator (>) return true on the same value as well ?
Your question seems poorly worded, but let me try anyway. Code like
double x = 0.6;
double y = 0.1 + 0.2 + 0.3;
May result in x == y being true or false. If you print x and y with 6 digits of precision they may appear to have the same value, but the machine stores more than 6 digits. You can see the full value by doing something like
union {
double d;
char hex[ sizeof(double) ];
} u;
u.d = x; print u.hex[]
u.d = y; print u.hex[]
Many times the hex[] values will not match, and then operator == will return false. Usually if == returns false, then either > or < will be true. There are obscure exceptions.

float/double equality with exact zero

I have an algorithm which uses floats or doubles to perform some calculations.
Example:
double a;
double b;
double c;
...
double result = c / (b - a);
if ((result > 0) && (result < small_number))
{
// result is relevant...
} else {
// result not required...
}
Now, I am worried about (b - a) might be zero. If it is close to zero but not zero, it does not matter because the result will be out of range to be useful, and I already detect that (as (b - a) approaches zero, result will approach +/- inf, which is not in the range 0-small_number...)
But if the result of (b - a) is exactly zero, I expect that something platform dependant will happen due to divide by zero. I could change the if statement to:
if ((!((b-a) == 0.0)) && ((result = c/(b-a)) > 0) && (result < small_number)) {
but I don't know if (b-a) == 0.0 will always detect equality with zero. I have seen there are multiple representations for exact zero in floating point? How can you test for them all without doing some epsilon check, which I don't need (a small epsilon will be ignored in my algorithm)?
What is the platform independant way to check?
EDIT:
Not sure if it was clear enough to people. Basically I want to know how to find if an expression like:
double result = numerator / denominator;
will result in a floating point exception, a cpu exception, a signal from the operating system or something else.... without actually performing the operating and seeing if it will "throw"... because detecting a "throw" of this nature seems to be complicated and platform specific.
Is ( (denominator==0.0) || (denominator==-0.0) ) ? "Will 'throw'" : "Won't 'throw'"; enough?
It depends on how b and a got their values. Zero has an exact representation in floating point format, but the bigger problem would be almost-but-not-quite zero values. It would always be safe to check:
if (abs(b-a) > 0.00000001 && ...
Where 0.00000001 is whatever value makes sense.
Here's how you do it: instead of checking for (result < small_number), you check for
(abs(c) < abs(b - a) * small_number)
Then all your troubles disappear! The computation of c/(b-a) will never overflow if this test is passed.
I guess you can use fpclassify(-0.0) == FP_ZERO . But this is only useful if you want to check if someone did put some kind of zero into float-type variable. As many already said if you want to check result of calculation you may get values very close to zero due to nature of representation.
In brief, we can know a floating number is ZERO exactly if we know it represent format.
In practice, we compare x with a small number. And if x is less than this number, we think x is as same as ZERO functionally (but most of time our small number is still large than zero). This method is very easy, efficient and can cross platform.
Actually, the float and double have been presented by special format, and the widely used one is IEEE 754 in current hardware which divided the number into sign, exponent and mantissa (significand) bits.
So, if we want to check if a float number is ZERO exactly, we can check if both exponent and mantissa is ZERO, see here.
In IEEE 754 binary floating point numbers, zero values are represented
by the biased exponent and significand both being zero. Negative zero
has the sign bit set to one.
Take float for example, we can write a simple code to extract exponent and mantissa bit and then check it.
#include <stdio.h>
typedef union {
float f;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} float_cast;
int isZero(float num) {
int flag = 0;
float_cast data;
data.f = num;
// Check both exponent and mantissa parts
if(data.parts.exponent == 0u && data.parts.mantissa == 0u) {
flag = 1;
} else {
flag = 0;
}
return(flag);
}
int main() {
float num1 = 0.f, num2 = -0.f, num3 = 1.2f;
printf("\n is zero of %f -> %d", num1, isZero(num1));
printf("\n is zero of %f -> %d", num2, isZero(num2));
printf("\n is zero of %f -> %d", num3, isZero(num3));
return(0);
}
Test results:
# is zero of 0.000000 -> 1
# is zero of -0.000000 -> 1
# is zero of 1.200000 -> 0
More examples:
Let's check when the float becomes real ZERO with code.
void test() {
int i =0;
float e = 1.f, small = 1.f;
for(i = 0; i < 40; i++) {
e *= 10.f;
small = 1.f/e;
printf("\nis %e zero? : %d", small, isZero(small));
}
return;
}
is 1.0000e-01 zero? : NO
is 1.0000e-02 zero? : NO
is 1.0000e-03 zero? : NO
is 1.0000e-04 zero? : NO
is 1.0000e-05 zero? : NO
is 1.0000e-06 zero? : NO
is 1.0000e-07 zero? : NO
is 1.0000e-08 zero? : NO
is 1.0000e-09 zero? : NO
is 1.0000e-10 zero? : NO
is 1.0000e-11 zero? : NO
is 1.0000e-12 zero? : NO
is 1.0000e-13 zero? : NO
is 1.0000e-14 zero? : NO
is 1.0000e-15 zero? : NO
is 1.0000e-16 zero? : NO
is 1.0000e-17 zero? : NO
is 1.0000e-18 zero? : NO
is 1.0000e-19 zero? : NO
is 1.0000e-20 zero? : NO
is 1.0000e-21 zero? : NO
is 1.0000e-22 zero? : NO
is 1.0000e-23 zero? : NO
is 1.0000e-24 zero? : NO
is 1.0000e-25 zero? : NO
is 1.0000e-26 zero? : NO
is 1.0000e-27 zero? : NO
is 1.0000e-28 zero? : NO
is 1.0000e-29 zero? : NO
is 1.0000e-30 zero? : NO
is 1.0000e-31 zero? : NO
is 1.0000e-32 zero? : NO
is 1.0000e-33 zero? : NO
is 1.0000e-34 zero? : NO
is 1.0000e-35 zero? : NO
is 1.0000e-36 zero? : NO
is 1.0000e-37 zero? : NO
is 1.0000e-38 zero? : NO
is 0.0000e+00 zero? : YES <-- 1e-39
is 0.0000e+00 zero? : YES <-- 1e-40
UPDATE (2016-01-04)
I've received some downvotes on this answer, and I wondered if I should just delete it. It seems the consensus (https://meta.stackexchange.com/questions/146403/should-i-delete-my-answers) is that deleting answers should only be done in extreme cases.
So, my answer is wrong. But I guess I'm leaving it up because it provides for an interesting "think out of the box" kind of thought experiment.
===============
Bingo,
You say you want to know if b-a == 0.
Another way of looking at this is to determine whether a == b. If a equals b, then b-a will be equal 0.
Another interesting idea I found:
http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Essentially, you take the floating point variables you have and tell the compiler to reinterpret them (bit for bit) as signed integers, as in the following:
if (*(int*)&b == *(int*)&a)
Then you are comparing integers, and not floating points. Maybe that will help? Maybe not. Good luck!
I believe that (b-a)==0 will be true exactly in those cases when the c/(b-a) would fail because of (b-a) being zero. The float maths is tricky but questioning this is exaggerating in my opinion. Also I believe that the (b-a)==0 is going to be equivalent to b!=a.
Distinguishing positive and negative 0 is also not necessary. See e.g. here Does float have a negative zero? (-0f)
For epsilon, in there is a standard template definition std::numeric_limits::epsilon(). I guess checking the difference to be bigger than std::numeric_limits::epsilon() should be safe enough to protect against division by zero. No platform dependency here I guess.
You could try
if ((b-a)!=(a-b) && ((result = c/(b-a)) > 0) && (result < small_number))) {
...

C++ Sgn Function

I saw the function below that should return sign of double d. But I couldn't understand how it works?
int sgn(double d){
return d<-eps?-1:d>eps;
}
return d<-eps?-1:d>eps;
That means:
If d is less than -eps, the result is "negative"
If d is more than eps, the result is "positive" (d>eps returns 1)
Otherwise we return 0 (meaning the number is "zero")
eps would normally be a small number, so we consider numbers between, say -1e-5 and 1e-5 as "practically zero". This approach is used to water down some deficiencies of the computer's floating-point numbers, like that sin(pi)!=0. However, it comes at the cost of introducing an arbitrary number eps in the calculation, and losing the property that eg. if a and b are positive numbers, a*b is positive provided underflow doesn't occur.
I suspect that eps is a very very small number, around 0.0000000001. If so, the function is using ternary notation to make an abbreviated form of:
int sgn(double d) {
if (d < -eps) {
return -1;
} else {
return d > eps;
}
}
That "return d > eps" part is probably there to make it return 0 if d == 0.0. Remember that expressions like "a > b" return boolean values, which become 1 if true or 0 if false.
So the function actually could return one of three values: -1 if the number is negative, 0 if it is zero, 1 if it is positive.
FLoating-point arithmetic has some peculiarities, like "machine epsilon" and -0 value. This solution uses machine epsilon to determine this '-0' case by using this machine epsilon, but is not completely correct: -0 = +0 = 0, always, you don't have to check for it. Also, this eps is not defined in your source: I guess It's defined elsewhere.
int sgn(double d){
return d<0? -1 : d>0; # -1, 0, +1. FIXED
}
much simpler, huh? :) in case d<0 it return -1. Otherwise, d>0 gives either 0 or 1, like d>0? 1: 0
P.S. Usually you don't check check the equality of floats: they're not precise and 20.6 can suddently (predictable, actually) become 20.000000000001. However, double precision is very high with values close to zero.
I suppose that eps is some very small value, really close to 0.
sgn function returns -1 is the value is lower than -eps, 0 if value is in [-eps,eps] and 1 if value is greater than eps.
eps is normally a very small value (greek letter epsilon is used in maths for a small increment)
So this says if the d is less than eps (eg. 0.00000001) return -1, else return 1 if it's greater than 0 and 0 if it's exactly 0

c++ rounding of numbers away from zero

Hi i want to round double numbers like this (away from zero) in C++:
4.2 ----> 5
5.7 ----> 6
-7.8 ----> -8
-34.2 ----> -35
What is the efficient way to do this?
inline double myround(double x)
{
return x < 0 ? floor(x) : ceil(x);
}
As mentioned in the article Huppie cites, this is best expressed as a template that works across all float types
See http://en.cppreference.com/w/cpp/numeric/math/floor and http://en.cppreference.com/w/cpp/numeric/math/floor
or, thanks to Pax, a non-function version:
x = (x < 0) ? floor(x) : ceil(x);
There is a nice article about a similar problem on CPlusPlus.com. The easy solution to your problem should be something like this:
double customRound( double value ) const {
return value < 0 ? floor( value ) : ceil( value );
}
A better solution is the one mentioned in the article, which uses a template:
//--------------------------------------------------------------------------
// symmetric round up
// Bias: away from zero
template <typename FloatType>
FloatType ceil0( const FloatType& value )
{
FloatType result = std::ceil( std::fabs( value ) );
return (value < 0.0) ? -result : result;
}
The x < 0 ? floor(x) : ceil(x); approach of Ruben Bartelink is good. Yet consider what happens with special cases of x = -0.0, x = NaN.
Rather than have myround(-0.0) potentially return +0.01 and have myround(NaN) return with a changed payload of the NaN, consider the below.
myround_alt(-0.0) returns -0.0.
myround_alt(NaN) more likely returns an unchanged payload NaN. Not-a-number stuff is tricky and not well defined. IAC, it is the myround_alt(-0.0) --> -0.0 I am seeking.
inline double myround_alt(double x) {
if (x > 0) return ceil(x);
if (x < 0) return floor(x);
return x;
}
1IEC 60559 floating-point arithmetic specifies ceil(±0) returns ±0 so this approach not needed with implementations that strictly follow that spec. Yet many C floating point implementation do not follow that (C does not require it) or fail in such comer cases like this.
try
double rounded = _copysign(ceil(abs(x)), x);