【问题标题】:Double to int implicit conversion in mingw32mingw32 中的 Double 到 int 隐式转换
【发布时间】:2015-02-05 08:18:36
【问题描述】:

我无法解释以下程序的行为(在 mingw 32 位上使用 gcc 编译)。我知道从 double 隐式转换为 int 时可能会丢失精度,但我希望这两种情况会给出相同的输出,因为它执行完全相同的操作。为什么两个输出不同?

#include <stdio.h>
#include <math.h>

int main()
{
    int table[3] = {2, 3, 4};
    int i, N;

    N = 0;
    N += table[0] * pow(100, 0);
    N += table[1] * pow(100, 1);
    N += table[2] * pow(100, 2);
    printf("%d\n", N);

    N = 0;
    for(i = 0; i < 3; i++)
        N += table[i] * pow(100, i);
    printf("%d\n", N);

    return 0;
}

//output: 
40302
40300

【问题讨论】:

    标签: c mingw32


    【解决方案1】:

    对于pow(100, 0) pow(100, 1)pow(100, 2),编译器将函数调用替换为常量(1, 100, 10000),但对于pow(100, i),它必须在运行时实际调用函数(因为变量i作为参数传递),导致pow0.9999999999.999999 的形式出现两个结果,而不是1100(或3 个中的任何2 个)。在乘法之后截断为 int 时,您会“丢失”两个单位。

    这是另一个例子,说明为什么从 double 转换为 int 只是纯粹的邪恶:很难在程序中找到细微的错误(而不是编译器错误)。

    顺便说一句,我很惊讶使用O2 的编译器没有展开循环、传播常量并达到相同的优化(用常量结果替换函数调用)。

    顺便说一句,我很惊讶编译器不会只用两次调用 printf 来替换所有代码。

    【讨论】:

    • 我认为值得一提的是,C标准实际上并没有指定“pow()”的精度,甚至“pow()”也没有为pow(0)给出相同的结果和 i=0 的 pow(i)。这对我来说真的很令人惊讶,但允许在非常小的嵌入式系统上进行优化是有意义的。
    • @Groo 您的链接指向不同的编译器(gcc 9.2 x86-64),因此结果不同也就不足为奇了。即使在循环中进行了三次迭代,我的问题的结果也无法用 gcc 9.2 重现,我的问题是针对 mingw-32bits GCC 的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 2020-05-03
    • 1970-01-01
    相关资源
    最近更新 更多