《C语言及程序设计》实践参考——sin泰勒展式中的错误

简介: 返回:贺老师课程教学链接  项目要求【项目1-sin泰勒展式中的错误】下面是sin函数的泰勒展式:(注:x取弧度值,而非角度值)编写了double mysin(double x)用于求sin值,却“死”在了123°上(122°度的结果已经出来了)。剧透一下,循环没有问题(当然问题会表现在循环中)。试着用调试工具找出问题出现在哪里,然后给出解决问题的方案。#include<std

返回:贺老师课程教学链接  项目要求


【项目1-sin泰勒展式中的错误】

下面是sin函数的泰勒展式:
(注:x取弧度值,而非角度值)
编写了double mysin(double x)用于求sin值,却“死”在了123°上(122°度的结果已经出来了)。剧透一下,循环没有问题(当然问题会表现在循环中)。试着用调试工具找出问题出现在哪里,然后给出解决问题的方案。

#include<stdio.h>
#define pi 3.1415926
double mysin(double x);
double myabs(double x);
int main( )
{
    double angle;
    for(angle=0; angle<=180; angle++)
        printf("sin(%.0f°) = %.3f\n", angle, mysin((angle/180)*pi));
    return 0;
}

//下面定义mysin函数,求sin值
double mysin(double x)
{
    double sum=x,x_pow=x,item;
    int n=1,fact=1, sign=1;     //定义变量时赋初值,已经将第一项考虑到累加和sum中
    do
    {
        fact=fact*(n+1)*(n+2);  //fact用于表示阶乘,在公式中作分母
        x_pow*=x*x;             //x_pow是分子中用于表示阶乘,在公式中作分母
        sign=-sign;             //确定即将要累加的这一项的符号
        item =x_pow/fact*sign; //计算出要累加的项
        sum+=item;              //将该项累加上去
        n+=2;
    }while(myabs(item)>1e-5);
    return sum;
}

//下面定义myabs函数
double myabs(double x)
{
    return ((x>=0)?x:-x);
}
提示:请进入到mysin中后,注意各变量的变化,看通项是否会收敛,从而使循环能够结束。


[参考解答]

(若需要参考,下面的锦囊逐个找开。你要是将所有锦囊全看了再干,……老贺会伤心的:每个锦囊里都有心血,一个一个做出来不容易。)

(若你在实施中,还有意外阻碍了你,请在评论中说明,帮助老贺细化锦囊。)

锦囊1:跟踪要进到mysin函数中,注意用step into。


锦囊2:跟踪mysin函数的执行,离不了进循环,你要是一直用next line(用step into不遇到自定义函数时效果也一样),点鼠标很单调,还容易分散注意力。请在循环中某语句上设置断点,用Debug/Continue按钮“跨越式”跟踪。



锦囊3:因为问题出在123°,你要是从0°开始跟踪mysin中的循环,我相信你看到这个锦囊时,大概angle不超过10(这已经说明你有足够的耐心了)。我们需要直接进入到对当角度是123°时对mysin的调用。有两种方法:

第一种:改一下main函数,例如(还可以有很多方式,只要能直接调用mysin(123°)即可):

int main( )
{
    double angle;
    printf(" %.3f\n", mysin((123/180)*pi));
    //for(angle=0; angle<=180; angle++)
    //    printf("sin(%.0f°) = %.3f\n", angle, mysin((angle/180)*pi));
    return 0;
}
第二种:在观察窗口(Watches)中,还可以在跟踪中改变变量的值,以便看到对应的执行结果。所以如下图,可以在进入到mysin函数之前,在观察窗口中加入angle(需要在系统自动出现的变量的下面,自己再输入变量名),然后在后面直接将想要的值输入。

其实还可以step into到mysin中后(或者通过断点直接进入到mysin中后),同样的办法修改x的值。


锦囊4:很可能你听了老贺的指点,用锦囊3中的第一种方法,却发现进到mysin后,x的值是0,不是123°对应的弧度值。
对不起,我故意挖个坑,你也就进来了。进来了,坐会儿再走。
求123°的sin值,不是调用mysin((123/180)*pi),而是mysin((123.0/180)*pi)!mysin((123/180)*pi)的确就是mysin(0),注意数据类型。
进了这个坑,就要知道,程序的修改,可能会引入新的错误。这是软件工程中的一个规律。


锦囊5:现在进入关键时刻(建议还是设好断点跟踪),你会发现问题在于,item的绝对值本来是逐渐递减趋于0的(这体现了泰勒公式的收敛性,实际上,当角度值没有达到123°时,这种收敛是能保证的),但是,某个时候,item的绝对值却又大了起来,退出循环的希望,逐渐渺茫,以致于失去了希望……你可以观察fact的值,这里也发生了一些似乎不可思议的事情。

锦囊到此,现象都有了,下面就需要你的诊断了。请试着解决这个问题。解决了,或者实在想不出来了,再看下面的“真相”。



真相(倒着看,一来你得活动活动身体了,二来,实在不想让你很容易地放弃自己给出解决方案的探索历程):


目录
相关文章
|
2月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
91 16
|
2月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
106 18
|
2月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
69 18
|
2月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
76 13
|
2月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
48 3
|
2月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
32 2
|
2月前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
62 1
|
C语言
《C语言及程序设计》实践参考——双分支结构流程图-大值
返回:贺老师课程教学链接  项目要求 【双分支结构流程图-大值】问题:画流程图,输入两个整数a和b,输出其中的大值。提示:采用双分支结构,输入a、b后,将大值赋值给另外一个变量,最后输出结果。 参考解答:
1666 0
|
C语言 知识图谱
《C语言及程序设计》实践参考——流程图综合-体重监测器
返回:贺老师课程教学链接  项目要求 【流程图综合-体重监测器】(1)成年男性的标准体重,标准体重(kg)= 身高(cm)-100,请画流程图,输入身高,输出标准体重。 (2)超标准体重20%为超重,请画流程图,先计算出标准体重,当超重时,请给出提示 (3)体重监测器需要在不超重时也给提示,请画流程图。 (4)若体重低于标准体重20%为超低,将这种情况也做出处理。 (5)除了为男生服务,还要
1441 0
|
C语言
《C语言及程序设计》实践参考——被3或者5整除的数
返回:贺老师课程教学链接  项目要求 【项目:被3或者5整除的数】编程序,输入一个数,判断它能否被3或者被5整除。如至少能被这两个数中的一个整除,则将此数打印出来,否则不打印。[参考解答] 解法1: #include &lt;stdio.h&gt; int main ( ) { int x; scanf("%d", &amp;x); if(x%3==0||x%5==
1301 0