#edu018. 第 4 节 绘制函数图像

第 4 节 绘制函数图像

利用 "描点法" 可以绘制函数图像,根据解析式可以计算出函数图像上的一些点的坐标,然后在坐标系中 "描点-连线" ,获得函数图像。利用计算机高效性,可以快速计算出点的坐标,然后在对应位置描点(画一个半径很小的实心圆),如果点的数量足够密集,点就可以聚集在一起,连成线,这就是绘制函数图像的基本原理。

要能够绘制函数图像,需要知道相关坐标和描点的知识:

  1. 移动画笔到指定坐标位置: pen.move(x,y);

    说明:直接把笔的位置移动到指定的坐标,movemove 命令不会画出线条,笔的方向也不会改变。

  2. 绘制一个半径为rr颜色为cc的实心圆: pen.oo(r,c);

    说明:以画笔所在位置为圆心,rr 为半径,cc 为颜色编号,画圆。 pen.oo(r,c)pen.oo(r,c) 画实心圆, pen.o(r,c)pen.o(r,c) 画空心圆。命令中省略 cc 时用当前笔的颜色画图。

  3. 显示坐标:showXY();

    说明:显示一个简单的黑色虚线坐标,这个命令有增强格式 showXY(mod,color)showXY(mod, color)modmod 可取 0,1,2,3,40,1,2,3,4 表示显示的方式,colorcolor 表示画坐标的颜色。

  4. 改变显示比例:pen.scale(r);

    说明:以一定的比例画图,这是把图形放大缩小的简单方法。比例值 rr 为正的小数。r>1r>1 时是放大;r<1r<1 时是缩小;r=1r=1 时回到正常比例状态。

例子1: 绘制二次函数 y=x2+2x+1y=x^2+2x+1 的图像

分析:xx 取值范围很大 [,+][-\infty ,+\infty ],我们可以缩小 xx 取值范围 [100,+100][-100 ,+100 ],绘制一段函数图像。如果循环变量定义成整型,每次自增 11,即步长11,代码如下:

showXY(2);   //显示坐标
for(int x=-100;x<=100;x=x+1)
{
	int y=x*x+2*x+1;
	pen.move(x,y);
	pen.oo(2);   //绘制一个半径为2的实心圆
}

可以得到函数图像:

二次函数图像

二次函数图像

如果缩小步长,将 x=x+1x=x+1 变为 x=x+0.1x=x+0.1 ,并不能得到连续的函数图像,究其原因就是整型变量 xx 无法存储小数, x=100+0.1x=-100+0.1 ,将 99.9-99.9 赋给变量 xx,整型变量 xx 只保留整数部分,得到 99-99 (本质是向 00 取整)。

需要定义能够存储小数的变量,也就是实数类型(浮点数), floatfloat 单精度和 doubledouble 双精度实数,由于floatfloat 有效位数只有 6677 位,程序设计竞赛中起步就使用 doubledouble

showXY(2);   //显示坐标
for(double x=-100;x<=100;x=x+0.1)
{
	double y=x*x+2*x+1;
	pen.move(x,y);
	pen.oo(2);   //绘制一个半径为2的实心圆
}

可以得到函数图像:

二次函数图像

二次函数图像(减小步长)

例子2: 绘制正弦函数 y=sin(x)y=sin(x) 的函数图像

分析:如果直接绘图,由于正弦函数值域[1,1][-1,1],无法看到细节,在绘图之前需要放大,利用 pen.scale(r)pen.scale(r) ,放大后描点对应的实心圆半径太大,需要将其半径缩小(最终显示半径最小为 11 )。

pen.scale(50);  //放大50倍
showXY();   
for(double x=-6.28;x<=6.28;x=x+0.01)
{
	double y=sin(x);
	pen.move(x,y);
	pen.oo(0.02);   //放大后半径为1
}

可以得到函数图像:

正弦函数

正弦函数

例子3: 在同一个坐标系中绘制余弦函数 y=cos(x)y=cos(x) 和对勾函数 y=x+1xy=x+\frac{1}{x} 的图像

分析:要绘制余弦函数,绘图之前放大,但是如何同时产生两个函数图像了?其实就是在描点时同一个 xx 描两个点

参考代码如下:

pen.scale(50);  //放大50倍
showXY();   
for(double x=-6.28;x<=6.28;x=x+0.01)
{
	double y=cos(x);
	pen.move(x,y);
	pen.oo(0.02);   //放大后半径为1
	
    //描另外一个点
	if(x!=0)    // 对勾函数x不能为0
	{
		double y=x+1/x;
		pen.move(x,y);
		pen.oo(0.02);   
	}
}

可以得到函数图像:

两个函数图像

两个函数图像

细心的读者会发现对勾函数在定义域 [1,1][-1,1] 点还是离散的,这是由于这段函数增长率太快,两个点之间距离太大,可以进一步缩小步长,但是理论上依然会存在离散的点。可以利用 pen.line(x,y)pen.line(x,y) 在画笔当前位置到坐标 (x,y)(x,y) 连一条直线(画笔也会移动到坐标 (x,y)(x,y) 处,保持画笔原来的方向),感兴趣读者可以自行进行尝试。