用C语言编程,使用pow函数

时间:2015-12-10 09:38:52

标签: c precision pow

这是我在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标记为1b标记为14,将c标记为49,如果标记为&# 34;根= -7.00和-7.00" ...而不是说"两个根都是-7.00"但如果我在pow(b,2)条件下将b*b替换为else if,则会显示后一种结果....为什么会这样?请解释一下。

4 个答案:

答案 0 :(得分:3)

请在代码中附上最低限度的工作示例。

无论如何,它适用于我的系统(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 Karzes所提到的,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代表的内存。

答案 1 :(得分:2)

这可能是一个精确的问题。 pow(b, 2.0)用于b肯定的算法可能类似exp(2.0 * log(b)),可能会生成一个非常接近196.0但不完全196的数字。比较失败但是当舍入到小数点后2位进行打印时结果仍然相同。请改为%g

b * b相反b = 14.0196完全一样计算。

顺便说一句,我在笔记本电脑上获得了适当的代码结果,你使用的操作系统和编译器是什么?

答案 2 :(得分:2)

使用pow(b, 2.0)通常不如b*b准确。虽然它们在数学上是相同的,但pow函数将执行类似exp(2.0 * log(b))的操作。它还需要对否定b等进行特殊检查。另外,在取平方根时,请使用sqrt(x)而不是pow(x, 0.5),原因类似:它会更快,更准确。

您的代码也将通过计算判别式一次并保存而不是复制代码来改进。

答案 3 :(得分:0)

本文将指导您为什么结果不同:https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

我建议你试试这个,看看是否有效。

((int)pow(b,2) - (4*a*c))>0 // Assuming computation is based on integers.

如果没有,请尝试这些建议(在C中使用类似功能):

What is the best way to compare floats for almost-equality in Python?