《Lua程序设计(第4版)》:第3章练习答案

目录

总结

练习

练习3.1

练习3.2

练习3.3

练习3.4

练习3.5

练习3.6

练习3.7


总结

数值类型:Lua语言中8种基本数据类型,其中表示数值的是number。数值类型又分为两种,分别是代表整型的 integer 和浮点数的 float

精简模式:在标准Lua下,整型是64位大小,浮点数是双精度的。在资源有限的平台下,可以通过宏 LUA_32BITS 编译出精简Lua ,精简模式下整型大小是32位,浮点数是单精度。

数值常量:表示数值常量时,小数点前后的内容都是可选的;如 3.1  .123  56.  都是正确的。

                  数值当然也可以用指数形式表示,如5E+20   .3e12  等前面的小数部分和之前相同,小数点前后内容都是可选的,指数部分必须是一个整数,不能是小数, e 和 E 都是可以的。

                  也可以在开头加 0x 或 0X 来表示十六进制,Lua 同样支持 C99 中的十六进制浮点数,由小数部分和以 p 或 P 开头的指数部分组成,十六进制小数虽然可读性很差,但是它的运算是精准的且格式输出时转换速度更快。

math.type函数:存在小数部分或者用指数形式表示的数值都认为是浮点型值,否则认为是整型。Lua标准库中的 math.type 函数会返回数值的类型(一个字符串),float 或 integer 。

算术运算:两个整型运算结果是整型,两个浮点型运算结果是浮点型,一个整型一个浮点型时先将整型值转换为浮点型然后运算。Lua 中整除( // )的结果会向负无穷取整,取余( % )运算的定义是 a % b== a - (( a // b) * b ),因此取模结果的符号和操作数 b 相同,这与C类语言中的取模运算大不相同,因为整除的结果是向负无穷取整,而不是向零取整。浮点数也可以进行取余和整除运算。

                 除法和指数运算的结果必然是浮点数,因此会将两个操作数都转化为浮点数后再进行运算。

关系运算:关系运算符有 > < <= >= == ~= ,关系运算的结果都是 boolean 类型,比较数值时相同子类型运算效率会更高。

位运算:Lua 中的位运算功能和 C 语言中的完全一致,异或的运算符号有所不同,Lua 语言中的异或运算符是 ~ ,和按位取反的符号相同。位运算只能对整型数使用,因此运算前会试图将两个操作数都转化为整型,如果转换失败(小数部分不为 0 ),会立即引发错误。

运算精度:标准 Lua 下整型最大值为 2^63 - 1,最小值为 -2^63 ,整型数的运算都是精确且可以预测的;而双精度浮点数能精确表示的整数范围被限制在 [ -2^53 , 2^53 ] 之间,超出这个范围后多出的位数不再存储,因此浮点数的运算必须要考虑精度损失的问题。

运算优先级:Lua 语言中运算符优先级从高到低依次是

                     ^

                     -   #   ~   not

                     *   /   //   %

                     +   -

                      ..

                      <<   >>

                       &

                       ~

                       |

                       <   >   <=   >=   ~=   ==

                       and

                       or

                       除幂运算和连接操作符是有结合外,其他运算符都是左结合的。

数学库:Lua 标准库中有标准数学库 math ,包含了一组常用数学函数。

              math.tointeger                                 浮点类型转整型,不成功则返回 nil

              math.type                                        返回数值类型的子类型,不是数值类型则返回 nil

              math.abs   math.sqrt                       绝对值/开方(Lua中用处不大,开方可以直接 x^0.5 )

              math.sin  math.cos  math.tan          正弦/余弦/正切

              math.asin  math.acos  math.atan    反正弦/反余弦/反正切

              math.ceil   math.floor   math.modf   向上取整/向下取整/得到整数和小数部分

              math.exp                                         计算 e^x

              math.rad   math.deg                        度数转弧度/弧度转度数

              math.fmod                                       C语言中的取余(整除是向零取整)

              math.log                                          对数运算,默认底数是 e

              math.max   math.min                      若干个数的最大值/最小值

              math.ult                                           把两个参数当作无符号数运算,当第一个参数小于第二个时返回true(整型参量)

             math.random   math.randomseed    产生随机数,默认产生[ 0,1 )的浮点数,还可以给定两个整型参数,返回[ x,y ]之间的整型随机数/重置随机数种子

             标准数学库中的常量

             math.huge                                        C语言math.h中的HUGE_VAL,无穷大

             math.maxinteger   math.mininteger 整型数的最大值/最小值

             math.pi                                             Pi 值

练习

练习3.1

.0e12 -> 0.0

0x12  -> 18

0xA  -> 10

0xFFFFFFFF  -> 4294967295

0x1P10  -> 1024.0

0.1e1  -> 1.0

0x0.1p1  -> 0.125

练习3.2

1. 乘2相当于左移1位,0111…1111左移1位后变为1111…1110,对应的原码值就是 -2

2. 1000…0000左移1位后变为 0000…0000,对应的原码值就是 0

3. 0111…1111 * 0111…1111 除最低位是1不变,其他位均发生进位后为 0(每高一位1的个数加1,进位得到的1也加一,一直保持偶数个1)

4. 最高位发生进位后,所有位都是 0

练习3.3

-10     2
-9      0
-8      1
-7      2
-6      0
-5      1
-4      2
-3      0
-2      1
-1      2
0       0
1       1
2       2
3       0
4       1
5       2
6       0
7       1
8       2
9       0
10      1

可以看出Lua 中向下取余的特性在正数时与C类语言中向零取余的结果是一样的,但在负数时Lua取余也是向下取整后加上余数等于被除数,C类语言中取余变为向上取整后加上余数等于被除数。

练习3.4

2.4178516392293e+024
4.1359030627651e-025

指数运算是从右到左

练习3.5

中文版翻译有错误,英文原版如下

Exercise 3.5: The number 12.7 is equal to the fraction 127/10, where the denominator is a power of ten. Can
you express it as a common fraction where the denominator is a power of two? What about the number 5.5?

 大致意思是12.7可以表示成以10为底的幂作为分母的分数,你能把12.7表示为以2为底的幂作为分母的分数吗?再试试5.5?

只需找到一个 2^n * 12.7 结果是一个整数,Lua中有两个简便的方法。

1.得到的结果对1取余,结果是0,因为Lua的浮点数也是可以取余哒,就很方便。

2.使用math.tointeger函数,如果不能转整型,函数会返回 nil ,这个特性也可以轻松判断是否是整数。

function exercise3_5(num)
  local base,sp,cnt=1,num,0
  while math.tointeger(sp)==nil do   --sp%1~=0 也可以
    base=base*2
    cnt=cnt+1
    if cnt==63 then
      io.write("Huge Number,Can Not Solve!\n")
      return
    end
    sp=num*base
  end
  sp=math.tointeger(sp)
  io.write("Got It , 2^",cnt,"\n");
  io.write(sp,"/",base,"=",sp/base);
  return
end

结果如下。

Got It , 2^48
3574732204225331/281474976710656=12.7

Got It , 2^1
11/2=5.5

练习3.6

角度值转弧度,公式出结果

function exercise3_6(h,p)
  return 1.0/3.0*((math.tan(math.rad(p))*h)^2.0*math.pi)*h
end

练习3.7

采用 Box-Muller 变换可以将均匀分布转化成正态分布

Z=R*cosθ 或 Z=R*sinθ (其中 R = sqrt(-2*ln(u1)), θ = 2*π*u2,u1和u2是(0,1]的均匀分布随机数,得到的Z就是标准正态分布随机数。

1. 生成均匀分布的随机数,math.random 函数生成的是 [ 0,1 ) 之间的随机数,只需在生成 0 时改为生成 1 。

2. 通过Box-Muller公式得到服从正态分布的随机数

function exercise3_7()
  local rand1,rand2=math.random(),math.random()
  rand1=rand1==0 and (1) or (rand1)
  rand2=(rand2==0) and (1) or (rand2)
  return math.sqrt(-2.0*(math.log(rand1)))*math.sin(2*math.pi*rand2);	
end

进行测试

tabexercise3_7={}
math.randomseed(os.time())
for i=1,10000000 do
  local sp=exercise3_7()
  sp=(sp+0.05)//0.1
  if tabexercise3_7[sp]==nil then
    tabexercise3_7[sp]=1
  else
    tabexercise3_7[sp]=tabexercise3_7[sp]+1
  end
end
for i=-100,100,1 do
  if tabexercise3_7[i]~=nil then
    print(i,tabexercise3_7[i])
  end
end
-46     4
-45     14
-44     26
-43     19
-42     67
-41     94
-40     156
-39     168
-38     295
-37     425
-36     593
-35     873
-34     1260
-33     1700
-32     2299
-31     3308
-30     4460
-29     5940
-28     7846
-27     10504
-26     13807
-25     17358
-24     22441
-23     28579
-22     35541
-21     43796
-20     54529
-19     65308
-18     78544
-17     94318
-16     110539
-15     129693
-14     148991
-13     171172
-12     194066
-11     218758
-10     242429
-9      266332
-8      289636
-7      312296
-6      332835
-5      351779
-4      367143
-3      381866
-2      391672
-1      397121
0       398882
1       396287
2       391313
3       380102
4       368257
5       351610
6       333307
7       312370
8       289953
9       265769
10      241824
11      218059
12      193944
13      171896
14      149872
15      130226
16      110792
17      94283
18      79484
19      65194
20      54156
21      43928
22      35677
23      28416
24      22303
25      17587
26      13716
27      10425
28      7858
29      6011
30      4462
31      3305
32      2368
33      1799
34      1164
35      906
36      651
37      458
38      291
39      170
40      130
41      89
42      41
43      28
44      18
45      8
46      11

 

END

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值