《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的值,这里也发生了一些似乎不可思议的事情。

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



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


目录
相关文章
|
29天前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
60 4
|
1月前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
1月前
|
C语言
【C语言】实践:贪吃蛇小游戏(附源码)(三)
【C语言】实践:贪吃蛇小游戏(附源码)
|
1月前
|
存储 API C语言
【C语言】实践:贪吃蛇小游戏(附源码)(一)
【C语言】实践:贪吃蛇小游戏(附源码)
|
1月前
|
C语言
用C语言写定积分的通用函数:sin(x),cos(x),eX.
用C语言写定积分的通用函数:sin(x),cos(x),eX.
29 0
|
1月前
|
存储 编译器 C语言
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
【C语言篇】数组和函数的实践:扫雷游戏(附源码)
35 0
|
1月前
|
程序员 编译器 数据处理
【C语言】深度解析:动态内存管理的机制与实践
【C语言】深度解析:动态内存管理的机制与实践
|
2月前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
|
2月前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
2月前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。