三维图形化C++趣味编程
上QQ阅读APP看书,第一时间看更新

第四章 追风逐电,毫发不伤

使用运算符

强大的魔法在于快速而准确地控制魔法元素,这离不开C++语言快速而准确的算术运算,C++语言用到的算术运算符如表4.1所示。

表4.1

C++语言没有提供数学中的中括号和大括号运算符,而统一以圆括号代替,例如数学算式{[3–(2–9)]–[(6–10)–(5–17)]},写成C++的表达式为((3-(2-9))-((6-10)-(5-17))),计算时由内到外计算圆括号里的值。

顺便提一下,诸如x2+y2这样的式子,写成C++的表达式为x*x+y*y。

【例4.1】魔导师的魔法力是123456789,大魔导师的魔法力是987654321,试编程计算两人的魔法力相加的和是多少。

参考代码如下所示:

程序中的a、b、c,我们称之为变量(类似于数学里的未知数x,y,z),变量是计算机语言中能储存计算结果或能表示值的量,通常值是可变的。与之相对应的,在程序中一旦值被定义就不允许改变的量,称为常量,例如圆周率Π的值就是3.1415926,是不允许改变的。

程序的第5~7行定义了a,b,c三个变量均为整数类型,int即表示整数类型。无论常量或变量,在使用前必须先指定其数据类型。不同的常量和变量只需定义一次。这相当于向计算机内存申请“房子”,只有住进“房子”里才可以在程序中使用,如图4.1所示。

图4.1

变量名只能由字母、数字、美元符和下划线等字符组成,且第一个字符必须为字母或下划线或美元符。

例如,合法的变量名有:_sum,average,Day,school_name,lotus_1_2,PASCAL,$sum

不合法的标识符和变量名有:Mr.Wang,234NUM,#34,a>=b,¥1234

第9和第10行分别从控制台窗口和绘图窗口输出结果。

c=a+b是计算出a+b的值后赋值给c,注意不能写成a+b=c。因为赋值运算符“=”不是数学里的“等号”,而是将右边的值赋值给左边的变量。

C++语言允许在定义变量的同时使变量初始化。例如int a=5;这行代码定义a为整型变量,初值为5。

诸如int a=5这样的语句,相当于下面两条语句:

      int a;
      a=5;

也可以使被定义的变量的一部分赋初值。如int a,b,c=5;这行代码定义了整型变量a,b,c,其中a和b的值未知,但c的初值为5,注意a,b,c之间用逗号分隔。

【例4.2】如图4.2所示,地球到太阳的平均距离大约为149597870千米,地球到月球的平均距离大约为384000千米,请编程算出地球到太阳的平均距离比地球到月球的平均距离多多少?

图4.2

参考代码如下所示:

图4.3

【例4.3】如图4.3所示,埃及金字塔内发现了一个神奇的数字142857,请编程把它从1乘到14看一看结果有何规律,例如142857×1的值为142857,142857×2的值为285714……

参考代码如下所示:

运行结果如图4.4所示。

图4.4

【例4.4】试编程计算9÷7、99÷7……999999÷7的值,并找出其中的规律。

参考代码如下所示:

运行结果如图4.5所示。

图4.5

C++语言里,整数与整数的除法,其结果仍然是整数,如果有小数部分会被舍弃,例如1/2的结果本来应该是0.5,但程序运行的结果却是0。

为了解决这个问题,可以定义变量的数据类型为实数类型(浮点数)即float或double,例如float d=7或double d=7,double类型的精度要高于float类型。

整数与浮点数运算,其结果为浮点数,例如计算99/7.0的值,此时7.0是浮点数,则运算结果也为浮点数。

任务 【题4.1】试改进上面的程序,使之可以显示小数。

【例4.5】7月1日是星期六,问7月20日是星期几?

参考程序如下所示:

7月1日到7月20日是20–1=19天。

19÷7=2(星期)……5(天)

将星期一至星期六以数字1~6表示,星期天以数字0表示,则7月20日为(6+5)÷7=1…4,所以7月20日是星期四。

程序中的余数运算符以%来表示,例如计算19÷7的余数可以写成19%7。

注意计算余数时,除数与被除数均应为整数。

在绘图窗口显示的参考程序如下所示。

第6行代码中使用了整数转字符串函数IntToString(),这是因为Win.Cout()不支持两种或两种以上数据类型的混合输出,所以统一转为字符串输出。

第7行代码定义了一个变量str为string类型的字符串。string类型的字符串非常强大,例如使用“+”可以将两个字符串合并成一个字符串。

第10行使用了浮点数转字符串函数FloatToString()。

任务 【题4.2】今天是星期三,从今天开始起,到第50天是星期几?

图4.6

任务 【题4.3】已知a=1,b=2,c=3,d=4,e=5,试计算图4.6的算式。

【例4.6】已知一组图形由左到右的排列顺序如图4.7所示,设球体编号为1,金字塔编号为2,请编程计算这组图形的第20个图形的编号。

图4.7

绘制以上图形的参考程序片断如下所示。

如图4.8所示,在平面内画两条互相垂直,并且有公共原点的数轴,其中横轴为x轴,纵轴为y轴。这样我们就说在平面上建立了平面直角坐标系,简称直角坐标系。该平面中的任何一个点,只要知道该点到x轴和y轴的距离,就可以确定该点在坐标系的唯一位置。

图4.8

Dev-C++智能开发平台的绘图窗口的二维平面是一个400×400单位的笛卡儿坐标系,如图4.9所示。

图4.9

移动画笔坐标的命令为Pen.Move(x,y),表示在原画笔的位置上,向x轴方向移动x个单位,向y轴方向移动y个单位。

此外还有个Pen.MoveTo(x,y),表示直接将画笔移到坐标(x,y)处。

任务 【题4.4】由立方体、圆环、心形和五角星四种几何体依次排列组成的倾斜向上的彩虹桥如图4.10所示,你的任务是:

图4.10

(1)试绘制部分彩虹桥(相邻图形的高度差为10个单位)(选做)。

(2)将立方体、圆环、心形和五角星分别编号为1、2、3和4,且每个图形的直线距离为30厘米,试问从最左端的立方体算起,到10米处距离最近的图形编号是多少?

绘制立方体:Model.Cube(22,1);其中22表示立方体边长,1表示显示模式为实体。

绘制圆环:Model.Torus(4,8,30,1);其中4表示内径,8表示外径,30表示显示精度,1表示显示模式为实体。

绘制心形:Model.Heart(0.1,5);其中0.1表示大小,5表示厚度。

绘制五角星:Model.Pentagram3D(5,3);其中5表示大小,3表示厚度。

如何计算10米处距离最近的图形编号是多少呢?

首先介绍一个取整的方法:int(number);这表示将括号里的数值number强制转换为整数,如果数值number有小数部分,则将小数部分完全舍弃只取整数部分。例如int(1.1)的值为1,int(1.99)的值也为1。

再介绍如何对一个浮点数四舍五入取整:例如当浮点数为1.7时,int(1.7+0.5)=2,当浮点数为1.4时,int(1.4+0.5)=1。

想一想,这个方法对解决该问题有什么用处吗?

图4.11

【例4.7】如图4.11所示,戴森球是一种设想中的巨型人造天体,这种结构包围恒星并且获得其绝大多数或全部的能量输出。已知建造戴森球是由无数的部件组成,最重要的核心部件有两种,我们称为A部件、B部件,其质量分别为2012345678吨、1912345678吨。

(1)试计算这两种部件的质量之和的后四位数。

(2)假设A部件需要12345678个,试计算12345678个A部件总质量的后四位数。

绘制戴森球的代码如下所示:

效果如图4.12所示。

图4.12

因为每种数据类型均有其取值范围,如果超过其取值范围,就会输出错误结果。常用数据类型的取值范围如表4.2所示。

表4.2

二进制位(bit)是计算机存储信息的最小单位,代表1个二进制数位,其值为0或1,可以表示两个状态/数值。

int类型的存储空间有32位,可以表示232=4294967296个数字,考虑到负数和0的存储,所以int的取值范围在–2147483648~2147483647之间。

显然程序如果在计算过程中超过了整数类型的取值范围就会出错。那么取实数类型行不行呢?

实数类型虽然取值范围是足够了,但是实数是不能够直接取余数的。

解决方法是使用下面的两个公式:

(1)(a+b)%c=(a%c+b%c)%c

(2)(a×b)%c=(a%c×b%c)%c

参考程序如下所示:

【例4.8】有一个用1到9组成的九位数,使得这个数的第一位能被1整除,前两位组成的两位数能被2整除,前三位组成的三位数能被3整除……以此类推,一直到整个九位数能被9整除。试判断381654729和391654728这两个数是否满足要求?

C++语言里,整数与整数的除法,其结果仍然是整数,如果有小数部分会被舍弃,例如1/2的结果本来应该是0.5,但程序运行的结果却是0。

我们可以利用这个特征来取一个数的前几位数,例如123/10的结果应该是12.3,但是如果定义123和10均为整数类型,那么运行123/10的结果应该是12。

整数与实数的运算,为了保证计算的精度,运算结果是实数。例如12*1.2=14.4。

参考程序如下所示:

图4.13

【例4.9】已知计算机最小存储单位是位,一个位可以保存1或者0,这样可以表示1或0两个二进制数,两位可以表示00、01、10、11四个二进制数,那么8位可以表示多少个二进制数,16位可以表示多少个二进制数呢?

首先介绍乘法原理,如图4.13所示,A地到B地有2条路,B地到C地有3条路,C地到D地有4条路,则A地到D地共有2×3×4=24(种)方案。

做一件事,完成它需要分成n个步骤,做第一步有m1种不同的方法,做第二步有m2种不同的方法……做第n步有mn种不同的方法。那么完成这件事共有N=m1×m2×m3×…×mn种不同的方法,这就是乘法原理。

根据乘法原理,每一位可以放0或1两种方案,则两位可以表示4个数,实际上就是2的2次方,三位可以表示8个数,即2的3次方。

所以8位可以表示2的8次方的数,16位可以表示2的16次方的数,但是如果用连乘的方法来计算的话,写出来的代码会不太美观,此处介绍一个很有用的函数:pow(a,b),它可以计算出a的b次方的值。

输入代码如下所示。

因为pow(a,b)计算出来的值是浮点数,所以用int()函数强制将浮点数转变为整数。

我倒没有想到用pow(a,b)这个函数,我是这么想的:例如求28的值,展开式子为:2×2×2×2×2×2×2×2,当然依次计算是很笨拙的。

可以看出,先计算出2×2=4的值,式子就变成了4×4×4×4的值;

计算出4×4=16的值后,式子就变成了计算16×16的值。

因此核心代码可以这样写:

     int a=2;
      a=a*a;
      a=a*a;
      a=a*a;
     Win.Cout(a);

聪明的你,知道怎么计算216的值了吧。

【例4.10】已知太空防御罩是一个标准的圆,其面积为31400平方千米,设绘图窗口的长度单位为千米,试编程绘制这个圆。

圆的面积是3.14×r2,显然根据这个公式就可以求出圆的半径,即r2=31400/3.14,得r=

其中称为平方根,又叫二次方根,它是平方的逆运算,例如42=16,则=4。C++语言里以sqrt来表示,例如sqrt(25)的值为5。

绘制空心圆的语句是Model.Circle1(r);

绘制实心圆的语句是Model.Circle2(r);

其中r为圆的半径。

参考代码如下所示:

【例4.11】月球可以近似地看成一个标准的球体,已知它的表面积有3800万平方千米,设绘图窗口的长度单位为0.1千米,试编程计算月球的半径并绘图。

已知球体的表面积S=4πr²,其中r为球体半径。

参考代码如下所示:

绘制图形显示如图4.14所示。

图4.14

const是C++程序里的关键字,表示所定义的类型为常量,程序中的第2行定义了一个常量Pi的值为3.1415926。

常量的值定义好后,在程序运行中其值不允许被更改,例如当设置Pi的值为常量后,再在随后的代码里写Pi=Pi*2之类的语句,编译时将会报错。

图4.15

【例4.12】如图4.15所示,楚继光每天都要从家到学校去上学,很幸运的是,他家和学校在一条直线上,已知楚继光家的坐标为(5,6),学校的坐标为(100,125),请你编程计算出从楚继光家到学校的距离。

绘制以上图形的参考代码如下所示:

Pen.Text(x,y,str)表示在坐标(xy)处显示字符串str。

设A点坐标为(x1y1),B点坐标为(x2y2),则计算AB两点之间的距离D的算式为

D=

参考程序如下所示。

任务 【题4.5】已知A点坐标为(-100,-125),B点坐标为(100,125),试计算AB两点之间的距离。

任务 【题4.6】如图4.16所示,圣魔法学院的主教学楼平面图是一个梯形,已知梯形的上底和下底的长度分别为15千米和30千米,梯形中红色三角形部分为高级魔法师才能去的场所,其面积是150平方千米,求梯形面积是多少。

图4.16

绘制图4.16的参考代码如下所示:

Model.Trangle(x1,y1,x2,y2,x3,y3)表示绘制一个三角形,三个点的坐标分别为(x1,y1),(x2,y2),(x3,y3)。

解这道题的方法是:根据三角形的面积公式是(底×高)/2,由此可以算出梯形的高,再将高代入梯形面积公式(上底+下底)×高/2即可。

任务 【题4.7】已知等腰三角形底边长为50,面积为300,试编程绘制该图形。

图4.17

任务 【题4.8】如图4.17所示,已知等边三角形底边长为50,该底边的两点坐标分别为(0,0)和(50,0),试编程绘制该图形。

此题的关键是计算出第三点的坐标,显然第三点的横坐标为25,而纵坐标可以根据直角三角形的勾股定理求出。

勾股定理是一个基本的几何定理,即如果设直角三角形的两条直角边长度分别是a和b,斜边长度是c,那么可以用数学语言表达:a2+b2=c2

【例4.13】如图4.18所示,有一对兔子,从出生后的第3个月起每个月都生一对兔子。小兔子长到第3个月又生一对兔子。如果生下的所有兔子都能成活,且所有的兔子都不会因年龄大而老死,问每个月(计算到第14个月)的兔子总数为多少?

图4.18

第一个月小兔子没有繁殖能力,所以还是一对;

两个月后,生下一对小兔后总数共有两对;

三个月以后,老兔子又生下一对,因为小兔子还没有繁殖能力,所以一共是三对;

……

这就是有名的斐波那契数列(Fibonacci),这个数列有如下特点:第1,2两个数为1,1。从第3个数开始,该数是其前面两个数之和。即:1,1,2,3,5,8,13,…

参考代码如下所示:

编译运行结果如图4.19所示。

图4.19

任务 【题4.9】有一个牧场,每天牧草都均匀生长。这片牧草可供10头牛吃20天,或可供15头牛吃10天。问这块牧场每天的长草量可供多少头牛吃?

我们把每头牛每天的吃草量看作单位“1”(1份),10头牛吃20天,吃了10×20=200(份),15头牛吃10天,吃了15×10=150(份)。这样多吃的份数是200–150=50(份),这是因为20–10=10(天)多出来的,那么平均每天的长草量是不是可以算出来了?现在知道怎么做了吧?

任务 【题4.10】一个立方体的边长为10.25厘米,问这个立方体的表面积是多少?体积是多少?

任务 【题4.11】一个长方形铁皮,宽是10厘米,四角剪去边长2厘米的正方形,做成一个容积为192立方厘米的铁盒子,原来这张铁皮的长是多少?

任务 【题4.12】试计算等差数列2,4,6,8,10,…,120的和。

(提示:等差数列的求和公式是:Sn=(a1+an)×n÷2,其中a1是首项,an是末项;求等差数列项数的公式是:n=(ana1)÷d+1,其中an是末项,a1是首项,d是公差)

任务 【题4.13】已知等差数列为3,6,9,12,15…,试计算第50项的值是多少?

(提示:求等差数列中某一项an的通项公式:an=a1+(n–1)×d,其中a1是首项,n是项数,d是公差)

任务 【题4.14】楚继光看一本故事书,第一天看25页,以后每天比前一天多看的页数相同,第25天看了97页,问每天比前一天多看多少页?

(提示:求等差数列的公差,可以运用公式d=(ana1)÷(n–1),其中an是末项,a1是首项,n是项数)

任务 【题4.15】5个小朋友A、B、C、D、E顺序围坐在一张圆桌旁做分糖游戏,初始时每人面前分别有10、20、30、40、50块糖,从第一个小朋友A开始,将自己的糖果均分三份(如果有多余糖果就立即吃掉)自己留一份,其余两份分给他的相邻的两个小朋友,接着第二个小朋友B同样这么做……问一轮后,每个小朋友手上分别有多少糖果?

任务 【题4.16】歌手大奖赛上6名评委给一位参赛者打分,6个人打分的平均分为9.6分,如果去掉一个最高分,这名参赛者的平均分为9.4分,如果去掉一个最低分,这名参赛者的平均分为9.8分,如果去掉一个最高分和一个最低分,这名参赛者的平均分是多少?

任务 【题4.17】甲乙丙三人共有24元钱,先由甲分钱给其他两人,所分给的数与各人已有数相同,随后乙,丙依此法分钱,一轮后每个人的钱数恰好一样多,求原先各人的钱数是多少?

任务 【题4.18】叶妍霜设计了一个电脑芯片,但这个芯片只能进行加法运算,不能进行减法、乘法和除法等运算,请试为该芯片编程,算出12,22,32,42,…,102的值并输出12+22+32+42+,…,+102的值。

(提示:考虑1,1+3,1+3+5,1+3+5+7,1+3+5+7+9的值各为多少。)

任务 【题4.19】圣魔法学院后山有一片大草地,每天都匀速生长草。这片草地可供15头牛吃18天,或可供60只羊吃12天。如果1头牛一天的吃草量等于3只羊一天的吃草量,问现在23头牛吃,可以吃多少天?