【问题标题】:Simple Windows Program runs in Linux Terminal but not in Windows cmd [duplicate]简单的 Windows 程序在 Linux 终端中运行,但不在 Windows cmd [重复]
【发布时间】:2020-07-01 01:03:43
【问题描述】:

我尝试使用 GDB 来查看“幕后”这段代码发生了什么。

目前我的 GDB 仅在 linux 终端中工作,并且如标题所述,每当我在这里运行此代码时,我都会得到预期的(逻辑)输出。

我认为问题在于return 来自func()

cmd 中运行相同的代码会给出“不相等”,而在terminal 中会给出“相等”。 为什么会这样?

我使用gcc编译代码

代码如下:

 #include <stdio.h>

double func(){
     double y= 5 ;
     return (double)y/3;

    /*// Code that works as expected:
    double y= (double)5/3;
    return y;
     */
}

    int main()
{

    double x ;
    x= (double)5/3;

    if (x == func())
        printf("%lf equal to %lf\n", x ,func());
    else
        printf("%lf not equal to %lf\n", x, func());

    return 0;
}

【问题讨论】:

  • 欢迎来到floating point math。两个系统上的xfunc() 有什么区别?这就是你开始弄清楚这一点的地方。它可能是小得离谱但非零的东西,比如 1e-29。
  • @tadman 所以 cmd 以不同于终端的方式解释双变量。但即便如此,我认为在 cmd 中 func()x 的处理方式相同,因为它们都是 double 数据类型。
  • 您在 Windows 构建中使用什么工具链?将有一个调试器。在任何情况下,你都可以在 Windows 中使用 GDB(如果使用 MinGW)。
  • 我在 cmd 中使用 gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 运行它,它工作正常,结果是 equal to
  • 这不是cmd 的函数,可能与您的编译器或编译器设置有关。 double 既可以表示为寄存器(通常为 80 位),也可以表示为 64 位的内存值。在这两者之间转换可能会导致值的微小差异,这意味着它们不是“等效的”。编译器优化也可以在这里发挥作用,在任何给定情况下以最有效的方式表示它。

标签: c debugging cmd terminal gdb


【解决方案1】:

您正在将编译器生成的常量与运行时生成的计算进行比较,然后使用不同的编译器编译它们并在不同的环境中运行它们,可能在不同的处理器上运行它们,并且您的非确定性代码会产生不同的结果。这应该不会让您感到惊讶。

进一步double 是 64 位类型,而 x86 FPU 支持 80 位浮点。此扩展精度可用于中间计算,但并非所有编译器都会为编译时常量或运行时计算这样做。

所有这些都是浮点结果的最低有效数字的不确定性的因素,通常不建议比较浮点类型是否相等。相反,您可以测试一些可接受的小差异:

#define EQUALITY_LIMIT FLT_EPSILON

if ( fabs(x - func()) < EQUALITY_LIMIT )
    printf("%lf equal to %lf\n", x ,func());
else
    printf("%lf not equal to %lf\n", x, func());

【讨论】:

  • 所以 `return (double)y/3` 是运行时生成的计算,它应该有大约 80 位。 x 有 64 位,这意味着存储了 15 位。我想return (double) y/3 存储的不止这些,这就是为什么等号不起作用的原因。这让我想知道为什么它可以在终端中工作。
  • @Robert - 不,我不是这么说的 - 它的类型为 double,并且是 64 位。在转换为double 之前,可能会或可能不会在内部使用 80 位。我只是提出一些可能导致比较浮点值是否相等的愚蠢问题。您必须比较汇编级代码和目标处理器 FPU 实现,以确定在这种情况下结果不同的确切原因。由于您没有指定这些变量(并且仍然奇怪地固定在“终端”与“cmd”而不是生成的代码上)。
  • @Robert :此外,不存储 15 位数字。双精度 binary 浮点表示恰好足以将 real 数逼近到至少 15 significant 十进制位精度。上一句的所有斜体部分对于理解这个概念至关重要。十进制和二进制表示之间没有完全一致,您要比较的是二进制值,因此它取决于最低有效位的差异,而不是最低有效十进制数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 2016-08-17
  • 1970-01-01
  • 2011-02-09
  • 2021-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多