c++ - Windows 与 Linux - 数学结果差异

标签 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 上,我得到 NaN 或一些与 Windows 比较小的数字。

我错过了什么?

编辑#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位

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

最佳答案

首先,没有真正的理由期待相同的结果, 除非你采取积极措施确保特定结果。这 C++语言定义允许使用中间结果 扩展精度。通常,如果编译器这样做(并且 这样做在英特尔架构上非常频繁), 扩展精度将被截断为标准 double 编译器存储到内存时的精度。而当它 存储到内存将取决于编译器的内部结构 (甚至可能在优化程度上)。

就英特尔而言,现代芯片包含多个 float 点处理器:较旧的 FPU 使用扩展精度,其中 因为较新的 SSE 变体没有。但是较新的 SSE 变体 在旧处理器上不可用。默认情况下,g++( Linux 编译器)使用较旧的 FPU,可以在任何地方工作,但是 据我所知,Visual C++ 使用 SSE。这意味着通过 默认,你会得到不同的结果。两个编译器都有 用于更改此选项的广泛选项,但如果您正在运行 默认配置,我希望 g++ 和 Visual 给出相同的结果。

关于c++ - Windows 与 Linux - 数学结果差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21183477/

相关文章:

c++ - 具有同一属性可以不同类型的属性的对象

linux - 我在进行 UDP 高速连续数据接收吗?

linux - libpcap 可以重组 TCP 段吗

windows - 使用cmd在windows中设置环境变量

c++ - std::initializer_list{x, y, z} (CTAD) 有效吗?

c++ - C++ 中 const 到非 const 的转换

c++ -::在C++中是什么意思?

linux - 导入签名证书问题 apache

C++ Windows 暂停定时器

windows - 如何从开发中服务 https Aurelia