c - 在 C 中使用文字值与计算值时答案不正确

标签 c function double return literals

首先让我说这是我学习 C 语言的第四天,如果我的代码不够简洁,请原谅我,但我相信它可以完成工作。另外,我想练习编写所有的数学函数,因为我觉得如果我自己编写它们会受益更多。我的编译器是 GNU gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

我在编写将度数转换为弧度的函数时遇到了这个错误。当我将 15 度的弧度值写入我的源代码时,我得到了正确的答案。然后我编写了从弧度转换度数的函数,用它来获取 15 度的弧度值,并将其插入到我的 sin(x) 函数中,它返回了一个不正确值。

然后我测试了很多不同的场景来尝试调试我的代码(正如您在所有 *printf* 中看到的那样)。然后我打印了我的计算弧度值的值(到 54 位十进制数字)并将该数字复制到我的源代码中......答案是正确的。

所以我的问题是:在什么情况下使用计算值会不同于使用相同的计算值,但直接复制到源代码中?

我知道编译器会自动转换任何文字值,如果它们与函数采用的参数的类型不同,但在我的例子中,我不明白它有何不同。

这是代码。再次抱歉,如果它很慢,但是嘿,这仅用于学习目的:) 任何帮助将不胜感激,我只是无法理解可能导致这种情况的原因,而且我 4 小时的研究毫无进展。

#include <stdio.h>

#define EPSILON 0.000001
#define PI 3.14159

double sin(double x);
int fact(int x);
double powr(double x, int power);
double deg_to_rad(double degrees);

int main(int argc, char *argv[]){

    double radian = deg_to_rad((double)15);

    printf("Correct answer = 0.25881883\n\n");
    printf("Sin approximation using constant .26179917: %1.8f\n\n", sin(.26179917));
    printf("Radian variable calculated by deg_to_rad(15): %1.54f\n", radian);
    printf("Sin approximation using radian variable: %1.8f\n\n", sin(radian));
    printf("Sin approximation using radian variable's value (0.261799166666666638381144593950011767446994781494140625) copied and pasted into source: %1.8f\n", sin(0.261799166666666638381144593950011767446994781494140625));

    return 0;
}

double deg_to_rad(double degrees){

    return ((degrees/180) * PI);
}

double abs_val(double x){

    if (x < 0){
        return (-x);
    }

    else{
        return x;
    }
}

int fact(int x){

    if (x > 1){
        return (x * fact(x - 1));
    }

    else return 1;
}

double powr(double x, int power){

    if (power < 1){

        if (power == 0){
            return 1.0L;
        }

        else{
            puts("This functionality is not yet built in to this function.");
            return 0.0L;
        }
    }

    else if (power > 1){
        return (x * powr(x , power - 1));
    }

    //If power is 1.
    else return x;
}

/*
* Based on the Taylor series: sin(x) = x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - ... +  (-1)^(n-1)*x^(2n-1)/(2n-1)! + ....
*/
double sin(double x){

    static int n = 0;
    n++;

    double result = (powr(-1.0L,n - 1) * (powr(x, (2*n - 1)) / fact(2*n - 1)));

    //If the current n is odd.
    if (n % 2){

        if (abs_val(result) > EPSILON){
            return (result + sin(x));
        }

        else {
            //Reset n and now begin returning from recursions.
            n = 0;
            return result;
        }
    }

    else {

        if (abs_val(result) > EPSILON){
            return (-result +  sin(x));
        }

        else {
            //reset n and now begin returning recurstion
            n = 0;
            return result;
        }
    }
}

最佳答案

调用 sin(constant) 是在编译时使用内置正弦函数计算的,而不是您的 sin。如果您使用 -fno-builtin 标志进行编译,或重命名您的函数,您的代码也将用于计算常量的值,并产生相同的(错误的)结果。

错误的结果是由于

if (abs_val(result) > EPSILON){
    return (-result +  sin(x));
}

在偶数 n 的情况下。该符号已经合并到 result 中,因此它也应该是 return result + sin(x),就像奇数 n 的情况一样。因此两个分支(应该)包含完全相同的代码,因此应该删除该分支。

此外,当其参数大于 12 时阶乘将溢出(对于带符号的 32 位 int),因此您的 sin 函数将不适用于参数需要超过六个项才能达到所需精度的大绝对值。

关于c - 在 C 中使用文字值与计算值时答案不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11389572/

相关文章:

c - 错误 '->' 的类型参数无效(有 'tree' )

javascript - 相同事件,相同效果,多个ID

vb.net - 你如何在 VB .NET 中将 Double 向下舍入到最接近的整数?

java - 将 double 从一项 Activity 转移到另一项 Activity

java - 如何在 Java 中创建指针数组?下面以c代码为例,对于我的项目JAVA是必修的,所以你能帮我吗?

c-不能打印成本

c - 使用 printf 四舍五入到最接近的十

c++ - 我如何在没有 Stod() 的情况下重写

c - C中void函数的return语句

C# 将 20 位精度 double 转换为字符串并再次返回