我有这段代码
#include <stdio.h>
#include <math.h>
static double const x = 665857;
static double const y = 470832;
int main(){
double z = x*x*x*x -y*y*y*y*4 - y*y*4;
printf("%f \n",z);
return 0;
}
这个方法的真正解决方案是1.正如我自己在前一个问题上已经回答的那样,这个代码由于灾难性的取消而失败了。但是,现在我发现了更奇怪的事情。如果你使用长多头,它可以工作,而据我所知,它们的范围小于双打。为什么呢?
答案 0 :(得分:4)
long long
的范围较小,但精度比double
更多。
但是,这不是在这里工作的。您的计算实际上也超出了long long
的范围,但由于在系统上处理整数溢出的方式,无论如何都会失去正确的结果。 (请注意,有符号整数溢出的行为不是由C标准固定的,但“通常”的行为与您在此处看到的相同)。
如果你看一下中间结果x*x*x*x
,你会看到如果你用double计算它,它有一个合理的值;不精确,但圆润,足以满足大多数用途。但是,如果你在long long
计算它,你会发现一个由于溢出而首先出现的数字绝对是疯子。
答案 1 :(得分:1)
在双尾中有尾数和指数的位。对于大双打,两个双精度(相同的指数,1加到尾数)结果之间的距离远远大于1.因此,你处于与无穷大+ 1 =无穷大相同的情况。
long long会溢出,计算模2“,因此当它应该为1时的结果确实可以是1。
答案 2 :(得分:0)
浮点类型的溢出可以被视为未定义或错误,具体取决于语言和环境。整数类型的溢出只是环绕(有时仍会产生正确的结果,有时不会)。