我有以下c程序,有些时候我运行它,输出不同,基于编译器和平台.我知道double to int转换可能会导致问题.
这是代码:
//Compiler version gcc 6.3.0
#include <stdio.h>
#include <math.h>
int main(void){
double d = 2;
printf("%.20lf\n", pow(10, d));
printf("%d\n", (int)pow(10, d));
printf("%d\n", (int)pow(10, 2));
}
Run Code Online (Sandbox Code Playgroud)
100是预期值,但声明
printf("%d\n", (int)pow(10, d));
Run Code Online (Sandbox Code Playgroud)
当我同时使用gcc 6.3.0和Windows 10 x64时,输出为99,但在其他情况下则不然.
以下是一些结果:
//gcc 6.3.0 (Sublime Text 3) in Windows 10 x64
100.00000000000000000000
99 ->this is the problem
100
//gcc 6.3.0 in Android (using Dcoder app)
100.00000000000000000000
100
100
//MSVC(VS 2017 x86) in Windows 10 x64
100.00000000000000000000
100
100
Run Code Online (Sandbox Code Playgroud)
我还测试了一些在线gcc(6.3.0)编译器,但所有输出都是100.
谢谢您的帮助.
一些pow返回值的实现不同于100 pow(10, 2).例如,可以返回99.9999999999999857891452847979962825775146484375.double转换为此值时int,结果为99.
这是pow实施质量的问题.pow如果可以获得精确的结果,那么好的实现会返
另外,我怀疑printf("%.20lf\n", pow(10, d))在Windows实现中没有正确格式化 - 它可能会将其内部转换为15位有效十进制数字,然后将其格式化为20位输出.您可以通过打印进行测试printf("%.20g\n", pow(10, d)-100).这将减去100 pow(10, d)的double算术.如果它显示非零输出,你知道它pow(10, d)不是100,所以printf("%.20lf\n", pow(10, d))显示不正确的结果.
注意,这pow是一个很难实现的功能.只有有限数量的案例具有确切的结果,因此大多数结果必然是不准确的.但是,即使在这些情况下,获得正确舍入到最接近的可表示值的结果也很困难.据我所知,没有人实现pow这种质量.大多数pow实现都允许一些额外的错误,因此您不应该依赖于pow正确舍入.但是,可以实现,pow以便确切结果可能的情况确实返回确切的结果,并且一些实现实现了这一点.