【发布时间】:2012-11-25 21:45:02
【问题描述】:
我有一些从 Java 移植到 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);
但在 C++ 中,r 可以是 +0.0 或 -0.0,当 r 等于 -0.0 时,检查失败。
我尝试在下面的代码中调整负零,但它从未到达 DEBUG("Negative zero") 行。但是r2 确实打印出等于+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);
有什么建议吗?
测试代码:
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);
测试结果:
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
海合会:
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)
标志:
CXXFLAGS += -g -Wall -fPIC
回答:
我已使用@amit 的答案来执行以下操作。
return (r>=(0.0-std::numeric_limits<double>::epsilon()));
这似乎有效。
【问题讨论】:
-
行为不标准。您使用的是什么编译器和浮点数学选项。我怀疑使用 fastmath 的 g++
-
另外,请发布一个完整且不太大的示例来展示该问题,并附上完整的构建说明,以便它可重现
-
谢谢。事实证明(见我的回答),只有描述的行为,关于“负零”比较不等于零,这是非标准的。实际上,显然没有负零,只有一个非常小的负值,对于给定的输出格式,它呈现为前面带有减号的所有零数字。
-
@Cheersandhth.-Alf and hth 是的,这就是问题所在。我使用 std::numeric_limits
::epsilon() 来帮助调整该问题。 -
哦,我忘了说:因为“问题”只是对所发生的事情的感知,所以到目前为止,最好的行动方案很可能是什么都不做(除了可能关于演示文稿)。通过与 epsilon 和 nulling 进行比较,您可能引入了一个错误。具有讽刺意味的是,当在错误感知的背景下进行评估时,这可能看起来是正确的行为。
标签: c++ algorithm negative-number