Detecting and adjusting for negative zero
algorithm, c++, negative-number
Solution
Well, a generic suggestion when using `double`s is remembering they are not exact. Thus, if equality is important - using some tolerance factor is usually advised.
In your case:
if (|r - 0.0| >= EPSILON)
where `EPSILON` is your tolerance factor, will yield true if `r` is not 0.0, with at least `EPSILON` interval.
Problem
I have some code that has been port from Java to C++ ``` // since this point is a vector from (0,0,0), we can just take the // dot product and compare double r = point.dot(normal); return (r>=0.0); ``` But in C++ `r` can be either `+0.0` or `-0.0`, when `r` equals `-0.0` it fails the check. I've tried to adjust for negative zero in the code below but it never hits the DEBUG("Negative zero") line. But `r2` does print out equal to `+0.0`. ``` // since this point is a vector from (0,0,0), we can just take the // dot product and compare double r = point.dot(normal); if (std::signbit(r)){ double r2 = r*-1; DEBUG("r=%f r=%f", r,r2); if (r2==0.0) { DEBUG("Negative zero"); r = 0.0; //Handle negative zero } } return (r>=0.0); ``` Any suggestion? TESTING CODE: ``` DEBUG("point=%s", point.toString().c_str()); DEBUG("normal=%s", normal->toString().c_str()); double r = point.dot(normal); DEBUG("r=%f", r); bool b = (r>=0.0); DEBUG("b=%u", b); ``` TESTING RESULTS: ``` DEBUG - point=Vector3D[ x=1,y=0,z=0 ] DEBUG - normal=Vector3D[ x=0,y=-0.0348995,z=0.0348782 ] DEBUG - r=0.000000 DEBUG - b=1 DEBUG - point=Vector3D[ x=1,y=0,z=0 ] DEBUG - normal=Vector3D[ x=-2.78269e-07,y=0.0174577,z=-0.0174391 ] DEBUG - r=-0.000000 DEBUG - b=0 ``` GCC: ``` Target: x86_64-linux-gnu --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ``` FLAGS: ``` CXXFLAGS += -g -Wall -fPIC ``` ANSWER: I've used @amit's answer to do the following. ``` return (r>=(0.0-std::numeric_limits<double>::epsilon())); ``` Which seems to work.