今天下午被一道很简单的题折腾惨了:
根据以下公式求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;
}
表示的范围
网友评论