我有以下代码:
#include <cstdio>
int main()
{
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当使用gcc(4.4,4.5和4.6)使用O3编译并本机运行(ubuntu 10.10)时,它会打印预期的"相等"结果.
但是,当如上所述编译并在虚拟机(ubuntu 10.10,virtualbox image)上运行时,它输出"不相等"的情况下相同的代码 - 这是O3和O2标志设置但不是O1及以下时的情况.当使用clang(O3和O2)编译并在虚拟机上运行时,我得到了正确的结果.
我理解1.1无法使用double正确表示,我读过"每个计算机科学家应该知道浮点算术的内容"所以请不要指向我那里,这似乎是GCC做的某种优化不知何故似乎在虚拟机中不起作用.
有任何想法吗?
注意:C++标准说在这种情况下类型提升是依赖于实现的,可能是GCC使用更精确的内部表示,当应用不等式测试时,它是否成立 - 由于额外的精度?
UPDATE1:以上修改上面的代码,现在得到了正确的结果.在某些时候,无论出于何种原因,GCC都会关闭浮点控制字.
#include <cstdio>
void set_dpfpu() { unsigned int mode = 0x27F; asm ("fldcw %0" : : "m" (*&mode));
int main()
{
set_dpfpu();
if ((1.0 + 0.1) != (1.0 + 0.1))
printf("not equal\n");
else
printf("equal\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
UPDATE2:对于那些询问代码的const表达性质的人,我已经改变了如下,并且在使用GCC编译时仍然失败. - 但我认为优化器也可能将以下内容转换为const表达式.
#include <cstdio>
void …Run Code Online (Sandbox Code Playgroud) c++ compiler-construction optimization double-precision vm-implementation
考虑这段 C 代码:
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
bool foo(int a, int b, int c, int d) {
double P = atan2(a, b);
double Q = atan2(c, d);
return P < Q;
}
bool bar(int a, int b, int c, int d) {
return atan2(a, b) < atan2(c, d);
}
int main() {
if (foo(2, 1, 2, 1)) puts("true"); else puts("false");
if (bar(2, 1, 2, 1)) puts("true"); else puts("false");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我用 编译它时gcc -lm -m64,它会打印
false …Run Code Online (Sandbox Code Playgroud) 我有一个为Linux x86 32位开发的应用程序.根据结果,有许多浮点运算和大量测试.现在我们将它移植到x86_64,但测试结果在这个架构中是不同的.我们不希望为每个体系结构保留单独的结果集.
根据GCC简介 - 对于GNU编译器gcc和g ++,问题是X86_64中的GCC假定fpmath = sse而x86假设fpmath = 387.387 FPU 对所有操作使用80位内部精度,仅将结果转换为给定的浮点类型(float,double或long double),而SSE使用操作数的类型来确定其内部精度.
我可以在编译自己的代码时强制-mfpmath = 387并且我的所有操作都正常工作,但每当我调用一些库函数(sin,cos,atan2等)时,结果都会再次出错.我认为这是因为libm是在没有fpmath覆盖的情况下编译的.
我尝试使用387仿真自己构建libm(glibc),但它导致了很多崩溃(不知道我做错了什么).
有没有办法强制进程中的所有代码在x86_64中使用387仿真?或者也许某些库在两种体系结构上都返回与libm相同的值?有什么建议?
关于"你需要80位精度"的问题,我不得不说这不是个别操作的问题.在这个简单的情况下,差异非常小,没有区别.但是,当复合很多操作时,错误会传播,并且最终结果的差异不再那么小,并且会产生影响.所以我想我需要80位精度.
我想确定给定的64位整数是否可以无损地存储在double中.现在我有这个代码:
static_cast<int64_t>(static_cast<double>(value)) == value
Run Code Online (Sandbox Code Playgroud)
但是,我认为由于某些平台上的精度过高,这并不总是准确的.
请注意,我不是要求最大的整数,以便所有较小的整数可以无损存储,即2 ^ 53.我需要知道给定的整数N是否无损存储,即使N + 1和N-1不是.
标准库中有什么东西,可能类似std::numeric_limits,会告诉我这个吗?
解
感谢@Michael Veksler的回答,我处于正确的位置以寻找解决方案。@Christoph,在这个岗位,建议尝试不同的编译器标志设置浮点运算的精度。
对我来说,-mpc32旗帜解决了这个问题。
我必须将C ++代码转换为C代码,因为新目标将没有C ++编译器。我遇到一个奇怪的事情,在C程序中运行时,与在C ++程序中运行时,数学方程式给出不同的结果。
方程:
float result = (float)(a+b-c+d+e);
Run Code Online (Sandbox Code Playgroud)
等式的元素都是浮点数。我通过检查每个元素的内存内容
printf("a : 0x%02X%02X%02X%02X\n",((unsigned char*)&a)[0],((unsigned char*)&a)[1],((unsigned char*)&a)[2],((unsigned char*)&a)[3]);
Run Code Online (Sandbox Code Playgroud)
在C和C ++中,abcd和e相等,但结果不同。
C语言中的计算示例:
a : 0x1D9969BB
b : 0x6CEDC83E
c : 0xAC89452F
d : 0xD2DC92B3
e : 0x4FE9F23C
result : 0xCD48D63E
Run Code Online (Sandbox Code Playgroud)
还有一个C ++示例:
a : 0x1D9969BB
b : 0x6CEDC83E
c : 0xAC89452F
d : 0xD2DC92B3
e : 0x4FE9F23C
result : 0xCC48D63E
Run Code Online (Sandbox Code Playgroud)
当我在更小的部分的方程分离,如在r = a + b随后r = r …