关于数据类型

2019-08-10  本文已影响0人  mark_x

今天下午被一道很简单的题折腾惨了:

根据以下公式求PI的近似值,要求正确计算出小数点后前7位(即3.1415926)


PI的近似公式

考察的循环求和,第一遍写的程序是这样:

#include <stdio.h>
#include <math.h>

int main(void)
{

    int sign = 1;
    int n = 1.0;
    float pi = 0.0, term = 1.0;
    
    
    while (fabs(term) > 1e-8)
    {
        pi = pi + term;
        n = n + 2;
        sign = -sign;
        term = sign / n;
    }
    
    pi = pi * 4;
    printf("PI = %0.7f\n", pi);
    
    return 0;
}

结果是4,显然,循环只执行了一次。
原因是:第一次进入循环时,term = sign / n, 由于定义n为整型变量,因此计算结果向下取整。即term = -1 / 3 -->0,第二次由于term = 0,不会进入循环,结果为4。

知道了原因后,将n定义为单精度浮点型float变量,然而发现程序死循环。
开始以为是精确到小数点后7位计算量比较大,程序一直在计算,然而始终没有停下来的迹象,确定是进入了死循环。为什么呢?

通过跟答案对比发现,答案采用的是双精度浮点型变量double。开始我没有在意是因为我有印象float的有效范围是10的好几十次方(查找资料后确定,float数值有效范围是-1038到1038,既然可以表示这么小的数,那么精度肯定足够啊,其实是混淆了一个概念。

① -1038
② 1038
③ 1 / 1038

我印象里把①和③想成相等了。。。

我之前一直以为float占的字节数比int多很多,而实际上它们都是4个字节,32位。
有符号整型int,1位表示正负,剩下的32位都可以表示数值,因此其范围是-231~231-1,大约在10的9次方左右。
而一样的占据一样的字节数,float是怎么可以表示那么大的值??float数值有效范围是-1038到1038
因为float是通过指数表示的,float的指数位有8位,也就是一个字节,表示的最大的数就是128,但是!在计算它的值的时候是2的128次方!!,所以它可以表示很大的数,但是这样表示是反科学的,理论上这样只能表示1, 2, 4, 8...这些数,那是怎么表示3, 5,6这些数呢?
这个好像很复杂,贴在这里以后再看吧。。。

浮点数好像很神奇的样子。。。
https://fishc.com.cn/forum.php?mod=viewthread&tid=67214&extra=page%3D1%26filter%3Dtypeid%26typeid%3D571

其实并不能表示的那么大,注意有效位数,说是1038,其实只有9位,也就是109左右


int main(void)
{

    int x1 = 123456789;
    int x2 = 12345678912;
    
    float y1 = 123456789;
    float y2 = 123456789123456789;
    float y3 = 123456789123456789123456789;
    
    printf("x1 = %d\n", x1);
    printf("x2 = %d\n", x2);
    printf("y1 = %.6f\n", y1);
    printf("y2 = %.6f\n", y2);
    printf("y3 = %.6f\n", y3);
    
    return 0;
}
表示的范围
上一篇 下一篇

猜你喜欢

热点阅读