Windows vs Linux - 数学结果差异

时间:2014-01-17 10:25:25

标签: c++ linux windows

我有C ++程序。如果我运行相同的代码部分,Linux和Windows会给出不同的结果。

#include <cmath>
#include <cfloat>
#include <cstdio>



#define MPI 3.141592653589793238462
#define DEG_TO_RAD(x) ((x) * 0.0174532925)
#define cot(x)  (1.0 / tan(x))
#define sec(x)  (1.0 / cos(x))

double p1 = DEG_TO_RAD(35);
double p2 = DEG_TO_RAD(65);

double lambertN = log(cos(p1) * sec(p2));
lambertN /= (log(tan(0.25 * MPI + 0.5 * p2) * cot(0.25 * MPI + 0.5 * p1)));


double t = tan(0.25 * MPI + 0.5 * p1);
double lambertF = cos(p1) * pow(t, lambertN);

//---------------------------

//specify input coordinates in degrees
double lon = 160.25;
double lat = 245.75;

double longitude = DEG_TO_RAD(lon - 10);
double latitude  = DEG_TO_RAD(lat);

double c = cot(0.25 * MPI + 0.5 * latitude);
double lambertPhi = lambertF * pow(c, lambertN);

printf("%f", lambertPhi); // here I got different results on Win and Linux

在Windows上,我得到了正确的结果(或者似乎是这样,因为最终结果还可以)。 在Linux上,我在Windows中获得了NaN或一些非常小的数字。

我错过了什么?

编辑#1:

Windows - Visual Studio 2010 - 通过GUI构建

Linux - gcc版本4.4.7 20120313(Red Hat 4.4.7-4)(GCC) - 使用makefile构建,标志:CFLAGS = -lm -lstdc ++ -Wall -O2

两个系统都是64位

PS: 如果有人感兴趣,这是Lambert-Conic投影方程的一部分。

2 个答案:

答案 0 :(得分:4)

首先,没有理由期待相同的结果, 除非您采取积极措施以确保具体结果。该 C ++语言定义允许使用中间结果 扩展精度。通常,如果编译器执行此操作(和 在英特尔架构上这样做很常见 扩展精度将被截断为标准双精度 编译器存储到内存时的精度。当它 存储到内存将取决于编译器的内部 (甚至可能在优化程度上)。

在英特尔的情况下,现代芯片包含多个浮动 点处理器:旧的FPU使用扩展精度,其中 因为较新的SSE变体没有。但较新的SSE变种 在较旧的处理器上不可用。默认情况下,g ++( Linux编译器)使用旧的FPU,无处不在,但是 据我所知,Visual C ++使用SSE。这意味着 默认情况下,您将获得不同的结果。两个编译器都有 改变这个的广泛选择,但如果你正在运行 默认配置,我期望g ++和Visual 给出相同的结果。

答案 1 :(得分:1)

我得到nan的{​​{1}}值介于90和270之间。这似乎是合理的,因为在该范围内,lat将返回一个负数,后来不能简单地将其提升为小数权力cot()

问题仍然是为什么你在Windows上得到不同的结果。但除非你提供有关具体输入值的信息,否则我不能多说。