CodeBlocks MinGw(Minimalist GNU For Windows)编译器下出现的不精确问题
如程序所示,我们最近在进行串口通信时,遇到的数字字符转化问题时发现的不精确问题
#include <stdio.h>
#include <math.h>int main()
{
int c=5;
int w=54321;//被除数
int i;
for(i=0;i<c;i++)
printf("%d\t",(int)pow(10,(c-i)));//输出被模运算的数
printf("%d\t",w%((int)(pow(10,(c-i)))));//输出模运算后的结果
printf("%d\t",(int)pow(10,(c-i-1)));//输出除数
s=w%((int)(pow(10,(c-i))))/((int)(pow(10,(c-i-1))));
printf("%d\n",s);//输出每一位数字
}
return 0;
}
理应是54321的最后一列,后变成了54361
仔细分析后发现:因为pow函数导致从double返回值类型向int型转化的时候是直接把小数部分切掉,
导致原先double型的小数部分不再四舍五入,从而失去了整数部分的精度,最终结果差1
可是:
#include <stdio.h>
#include <math.h>
int main()
{
printf("%d\n",(int)(pow(10,1)));
printf("%d\n",(int)(pow(10,2)));
printf("%d\n",(int)(pow(10,3)));
printf("%d\n",(int)(pow(10,4)));
printf("%d\n",(int)(pow(10,5)));
return 0;
}
对比下面的代码:
#include <stdio.h>
#include <math.h>
int main()
{
int i;
for(i=0;i<6;i++)
{
printf("%d\n",(int)(pow(10,i)));
}
return 0;
}
一开始我也总觉得这是编译器的问题,这样来看也许并不是,对于常量的存储,我是不太知道是怎么回事的于是参考别人的 说法是这样:常量又称为字面值常量,字面值常量在程序中是直接表示的,整型直接写出大小,字符直接写出字符。一个字面值常量在编译时被直接解析为立即数,编译器内部维护字面值常量的类型。它跟常量表达式不是一个概念,常量表达式是const型变量。
内存分为5个部分:栈区(局部变量),堆区(malloc函数),静态(全局)区,文字常量区,程序代码区
常数当然就在文字常量区,而下面的int i;则在栈区,存储的位置不一样结构肯定也不同,编译器处理也可能不同,从而也导致了结果的不同。
当然想要知道细节还是要pow函数的源码。
还有一个关于二进制数的理解我觉得很有意思---把浮点数当做模拟值(连续的),而用二进制表示浮点数是无法表示所有值的所以就造成了误差(附上地址):https://blog.csdn.net/qq_25847123/article/details/77587575