mingw32 中的 Double 到 int 隐式转换

Posted

技术标签:

【中文标题】mingw32 中的 Double 到 int 隐式转换【英文标题】:Double to int implicit conversion in mingw32 【发布时间】: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

【问题讨论】:

【参考方案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)。这对我来说真的很令人惊讶,但允许在非常小的嵌入式系统上进行优化是有意义的。 有趣的是,编译器optimized this away when the loop has only two iterations. @Groo 您的链接指向不同的编译器(gcc 9.2 x86-64),因此结果不同也就不足为奇了。即使在循环中进行了三次迭代,我的问题的结果也无法用 gcc 9.2 重现,我的问题是针对 mingw-32bits GCC 的。

以上是关于mingw32 中的 Double 到 int 隐式转换的主要内容,如果未能解决你的问题,请参考以下文章

为啥 int 被提升为 double 而不是 float 以进行隐式转换

BigQuery 加载镶木地板错误 - Parquet 中的字段 INT32 与架构中的 double 类型不兼容

从具体化的“System.Int32”类型到“System.Double”类型的指定转换无效

C#的(int) /int.Parse()/int.TryParse()/Convent.ToInt32()的区别--推荐使用Int.TryParse()

java中的数据在啥时候可能会发生隐式转换?

Scala 如何将 Int 转换为 Double?