这道题的考察点是溢出的判断,参考组成原理的知识,首先两个符号不同的数相加是不可能溢出的。在计算机内部,两个正整数相加是采用补码相加,如果和的符号为负,就代表正溢出;同理两个负数相加,和的符号为正,则代表负溢出。
参考代码如下:
#include<stdio.h>
int main(){
int line=0;
long long a,b,c;
scanf("%d",&line);
for(int i=1;i<=line;i++){
scanf("%lld%lld%lld",&a,&b,&c);
long long temp=a+b;
if(a>0&&b>0&&temp<0) printf("Case #%d: true\n",i);
else if(a<0&&b<0&&temp>=0) printf("Case #%d: false\n",i);
else if(temp>c)printf("Case #%d: true\n",i);
else printf("Case #%d: false\n",i);
}
}
一开始看到数据范围为[-263,263 ],右边界已经超出了long long的范围,于是本人使用double来记录a,b和c,以为double范围够大了,不会有问题,结果发现答案错误。经过查证,浮点数在计算机内部并不像整数一样直接化成补码存储,而是参照IEEE754标准来存储。
简单介绍一下IEEE754标准。该标准简单表示如下图。

在此标准中,浮点数类型会先转成一种类似于科学计数法的形式,分成数字符号,阶码(指数),尾数三个部分存储。存储时,最高位为数符位;其后为阶码,以移码方式存储,底总是2,就不存了;尾数采用原码存储,存储前必须经过在规格化,规格化过程中对应的阶码也会做调整,存储的尾数是纯小数。对于double类型,尾数最多能存53位(因为规格化后最高数值总是1,便没有存,以便可以多存一个尾数)。所以对于[-263,263 ],double无法存储63位尾数,存在精度丢失问题,所以说溢出这个考察点是逃不掉的。
至于A+B为什么不能直接与C相比较,本人查阅知乎link,发现表达式与变量比较,变量与变量比较这两者的比较机制是不一样的,看不懂(惭愧),但是本人觉得这个不能直接比较的问题是溢出造出的。
用long long没有出问题,因此数据范围应该有问题,[-263,263 )更符合。
本文探讨了编程中判断溢出的难点,重点在于整数溢出规则、浮点数IEEE754标准及其局限,以及为何A+B与C比较的问题。案例涉及longlong与double在[-263,263]范围内的精度问题,揭示了溢出在数据范围选择和比较运算中的重要性。
991

被折叠的 条评论
为什么被折叠?



