这是我用C程序写的代码的一部分
else if((pow(b,2.0)-4*a*c)>0) {
printf("\nRoots=%.2f and %.2f\n",
(-b+pow(b*b-4*a*c,0.5))/(2*a),
(-b-pow(b*b-4*a*c,0.5))/(2*a));
} else
printf("\nBoth roots are %.2f\n",-b/(2*a));在控制台中,如果我把a写成1,b写成14,c写成49,如果写成"Roots =-7.00 and -7.00“...不是说“两个根都是-7.00”,但是如果我在else if条件中用b*b替换pow(b,2),它会显示后面的结果……为何会这样呢?请解释一下。
发布于 2015-12-10 17:53:14
请在您的代码中包含一个最小的工作示例。
无论如何,它可以在我的系统上运行(Debian GNU/Linux测试,gcc 5.2.1):
#include <math.h>
#include <stdio.h>
int main() {
float a,b,c;
scanf("%f",&a);
scanf("%f",&b);
scanf("%f",&c);
if ((pow(b,2.0)-4*a*c)<0)
printf("\nNo roots!\n");
else if((pow(b,2.0)-4*a*c)>0) {
printf("\nRoots=%.2f and %.2f\n",
(-b+pow(b*b-4*a*c,0.5))/(2*a),
(-b-pow(b*b-4*a*c,0.5))/(2*a));
} else
printf("\nBoth roots are %.2f\n",-b/(2*a));
return 0;
}如果我输入1,14,49,程序会回答Both roots are -7.0。但这在不同的系统中可能会有所不同,因为您使用的是浮点运算,而我不知道您的pow()函数是如何实现的。并非所有的实数都可以在计算机上表示--这里很好地描述了它是如何在single precision floats上工作的。并且每个编译器/运行时环境都可能有不同的数学库实现(包括您使用的pow )。
所以,如果可能的话,我会尽量避免使用pow。改为使用b*b,并将pow保存到真正需要它的时候。正如Tom Karze提到的,在计算平方根方面,sqrt也比使用pow更好。
最后一件事:只计算一次判别式将使您的程序更具可读性:
#include <math.h>
#include <stdio.h>
int main() {
float a,b,c;
float delta;
scanf("%f",&a);
scanf("%f",&b);
scanf("%f",&c);
delta = b*b-4*a*c;
if (delta<0)
printf("\nNo roots!\n");
else if(delta>0)
printf("\nRoots=%.2f and %.2f\n",
(-b+sqrt(delta))/(2*a),
(-b-sqrt(delta))/(2*a));
else
printf("\nBoth roots are %.2f\n",-b/(2*a));
return 0;
}您可以尝试的另一件事是使用double而不是float,这样可以获得更高的精度(与要使用的数字无关,但如果没有占用太多内存的巨大数字矩阵,则使用doubles是个好主意-- double表示的内存是float的两倍)。
发布于 2015-12-10 17:47:56
这可能是一个精度问题。pow(b, 2.0)对b阳性使用的算法可能类似于exp(2.0 * log(b)),并可能产生一个非常接近196.0但不完全是196的数字。比较失败,但当四舍五入到两个小数位以进行打印时,结果看起来仍然相同。请尝试使用%g。
相反,b = 14.0的b * b计算结果与196完全相同。
顺便说一句,我在我的笔记本电脑上得到了你的代码的正确结果,你使用什么操作系统和编译器?
发布于 2015-12-10 17:57:03
使用pow(b, 2.0)通常不如使用b*b准确。虽然它们在数学上是相同的,但pow函数将执行类似于exp(2.0 * log(b))的操作。它还需要对负b等进行特殊检查。此外,在取平方根时,出于类似的原因,使用sqrt(x)而不是pow(x, 0.5):它会更快更准确。
通过计算一次判别式并保存它,而不是复制代码,您的代码也将得到改进。
https://stackoverflow.com/questions/34198267
复制相似问题