关于【深基】习题2-4的问题

回复帖子

@shellee 2021-05-03 20:26 回复

【深基】习题2.4原题:

阅读下列程序,猜测结果,并上机验证。

#include<cstdio>
using namespace std;
int main(){
    float a=0.1;
    printf("%d",int(2-a*a*100));
    //printf("%.10f",2-a*a*100);
    return 0;
 }

预测结果:1; 洛谷在线ide( luogu.com.cn/ide )运行结果:0

猜测类型强制转换引起的误差、浮点数运算产生的误差或者printf函数取舍造成的误差,遂进行下列代码验证猜想。

#include<cstdio>
using namespace std;
int main(){
    float a=0.1;
    printf("%d\n",int(2-a*a*100));
    printf("%d\n",int(a*a*100));
    printf("%.10f\n",a*a*100);
    printf("%.10f\n",2-a*a*100);
    printf("%f\n",2-a*a*100);
    printf("%f\n",a*a*100);
    return 0;
 }

洛谷在线ide( luogu.com.cn/ide )运行结果:

0
1
1.0000001192
0.9999998808
1.000000
1.000000

请各位大佬帮忙看下为何会造成这样的误差,避免误差的办法又有哪些呢?感激不尽

@andyli  2021-05-03 20:35 回复 举报

原因:

  1. 二进制无法准确表示十进制数据
  2. 保存浮点数的精度有限

方法:误差无法避免

@shellee 2021-05-03 20:58 回复 举报

@andyli @zhaoyp 感谢回答问题。 看到@zhaoyp 的回答,我运行了下面的代码。

#include<cstdio>
using namespace std;
int main(){
    float a=0.1;
    double b=0.1;
    printf("%d\n",int(2-a*a*100));
    printf("%d\n",int(a*a*100));
    printf("%.10f\n",a*a*100);
    printf("%.10f\n",2-a*a*100);
    printf("%f\n",2-a*a*100);
    printf("%f\n",a*a*100);
    printf("%d\n",int(2-b*b*100));
    printf("%d\n",int(b*b*100));
    printf("%.10f\n",b*b*100);
    printf("%.10f\n",2-b*b*100);
    printf("%f\n",2-b*b*100);
    printf("%f\n",b*b*100);
    return 0;
 }

得倒了下面的运行结果:

0
1
1.0000001192
0.9999998808
1.000000
1.000000
0
1
1.0000000000
1.0000000000
1.000000
1.000000

其中

 printf("%d\n",int(2-b*b*100));

这条代码的运行结果是0;而其余的将浮点数精度提升到double的代码运行结果都为1; 麻烦再次解惑,感激不敬

@zhaoyp  2021-05-03 21:23 回复 举报

改为

printf("%d\n",2-int(b*b*100));

可能是由于浮点数精度问题,导致 $b \times b \times 100$ 结果略大于 $1.0000000000$。

这有点超出我的能力范围了。不过考试也不会这么考你。

@shellee

反馈
如果你认为某个帖子有问题,欢迎向洛谷反馈,以帮助更多的同学。



请具体说明理由,以增加反馈的可信度。