【题目描述】
输入正整数n(n<360),输出n度的正弦、余弦函数值。提示:使用数学函数。
【解析】
这道题本身很简单,但涉及到两个转换问题值得一谈,搞清楚这两个转换,你就能知道编程和数学的差异在哪里了。
考查知识点
题目考查的知识点有3个:
1)单位转换
角度与弧度的转换。在C/C++中,sin、cos等三角函数的参数都用的是弧度值,题中给的n是角度值,应转化为弧度值。已知 π = 18 0 ∘ \pi=180^\circ π=180∘,故n的弧度值为n*π/180。
2)数据类型转换
这是经常被忽略的一个问题。单纯从数学角度讲,只存在一个“单位转换”的问题,但是从编程角度讲,就多了一个“数据类型转换”问题。
这是因为“程序=算法+数据结构”,单位转换本质上是一个算法问题,算法本质上就是数学问题,而数据类型转换是一个数据结构问题——即数据在计算机中的存储方式问题。
数据结构看起来好像深不可测,但本质上就是一种数学的表示。只不过在没有计算机之前,数学以各种数学符号、公式的形式表示,而在计算机中,全部用1和0表示。
数学本身是抽象的,但数学又是为解决具体的应用的,所以数学的应用是具体的。数学表示是数学由抽象转为具体的第一步。
回到题目,本题需要从角度转换为弧度,本来数据类型都可以设为浮点数,但是题干要求角度为“正整数n”,所以必须先将n转换为浮点数。
3)π的定义
π是个常数,所以应用const关键字声明常数。有些书中这样定义π:
const double pi = 3.14;
这样的代码在算法竞赛中是有问题的,因为它只精确到两位小数,而算法竞赛中经常会要求结果保留n位小数,如果n>2显然就会输出错误的结果。
完美的代码是这样的:
const double pi = acos(-1.0);
因为cos(π)=-1,所以反余弦函数acos(-1.0)值就是π [注:反余弦函数acos(x)会返回一个角度,这个角度的余弦值等于x。]
有一点需要说明的是,如果acos(-1.0)写成acos(-1)也是可以的,而且在cppreference中给出的模板代码就是这样写的:
但是在刘汝佳《算法竞赛入门经典》书中的代码用的是acos(-1.0),老金也觉得用这种方式是更好的习惯。因为我们脑子里要始终有一根弦:1代表整数,1.0代表浮点数。acos(x)的参数要求是浮点数,所以最好用1.0。如果你习惯了用acos(-1),那么有一天你就可能会写出acos(-1/2),这就会输出错误的结果。因为程序会按“整数/整数=整数”的算法求解,-1/2的计算结果-0.5的整数部分-0,也就是0,故acos(-1/2)= acos(0)= π/2,而acos(-1.0/2)= acos(-0.5)=2π/3。
关于π定义,更详细的内容介绍参见:如何完美定义π?
代码
C语言代码如下:
#include<stdio.h>
#include<math.h>
int main(){
const double pi = acos(-1.0);
int n;
double radian;//定义弧度变量,注意数据类型为浮点型
scanf("%d", &n);
radian = n*pi/180; //角度值转换为弧度值
printf("%f\n", sin(radian));
printf("%f\n", cos(radian));
return 0;
}