【问题标题】:Windows vs Linux - math result differenceWindows vs Linux - 数学结果差异
【发布时间】:2014-02-06 15:22:21
【问题描述】:

我有 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 位的

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

【问题讨论】:

  • 你应该告诉你正在使用什么编译器。还有,这个sn -p 还不够编译试试。您可以自己做的是逐步完成程序的这一部分并比较两个平台上的值,以找出两个版本开始分歧的地方。
  • 我认为我们需要一个合适的 SSCCE,以及​​两个环境的精确细节。编译器版本,32/64 位等
  • @MartinPerry lon 和 lat 的类型和值是什么,请添加 标头以获得可编译代码。
  • 我刚刚分别为lonlat 选择了值12045,并得到了一个有效的0.686144 作为输出。对我来说没有NaN。请提供您遇到问题的 lonlat 值。
  • 为什么我们不能有 SSCCE?你不想回答吗?您不想确保我们编译的代码与您完全相同吗?

标签: c++ linux windows


【解决方案1】:

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

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

【讨论】:

  • 这不取决于它是 32 位还是 64 位代码?所有 64 位 x86 处理器都有 SSE,所以我认为 GCC 和 MSVC 都默认使用 SSE 来处理 64 位代码。在 32 位模式下,我也不知道默认值是什么。
  • @Zboson 可以。我目前只使用 32 位模式,所以我不确定 64 位模式下的默认值是什么。
【解决方案2】:

对于介于 90 和 270 之间的 lat 值,我得到了 nans。这似乎是合理的,因为在该范围内,cot() 将返回一个负数,该负数以后不能简单地用 pow 提高到分数幂。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2015-05-05
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多