pow()函数结果强制转化为int造成误差的分析

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






猜你喜欢

转载自blog.csdn.net/changer_WE/article/details/80379171