目录
总结
练习
练习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