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
作为参数传递),导致pow
以0.99999999
和99.999999
的形式出现两个结果,而不是1
和100
(或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()