lua number类型详解(转载)

lua number类型详解和math.floor存在误差的问题

一、Lua number数据类型

  • lua的number类型,是默认当成双精度浮点类型来运算的。也就是说number会底层当做double类型来处理,精度是16~17位
  • 在Lua 5.2及之前的版本中,所有的数值双精度类型的实浮点数格式表示
  • 从Lua 5.3版本开始,Lua语言为数值格式提供了两种选择:
    • 整型值:称为interger的64位整型
    • 浮点型值:称为float的双精度浮点类型

二、类型判断

type()函数

  • 使用type()函数可以获取整型值和浮点型值的类型,返回的都是number(表示数值类型)

    print(type(3)) 			--number
     
    print(type(3.5))		--number
     
    print(type(3.14e3))		--number
    

math.type()函数

  • **如果想要区分整型值和浮点型值,**可以使用这个函数

    print(math.type(3))		--integer
     
    print(math.type(3.5))	--float
     
    print(math.type(3.14e3)) --float
    

三、十六进制表示

  • Lua也支持以0x开头的十六进制常量
  • Lua不仅支持十六进制的整型、还支持十六进制的浮点数
print(0xff)				--255

print(0x1A3)			--419

print(0x0.2)			--0.125
  • 十六进制浮点数还可以由小数部分和以p或P开头的指数部分组成**。
  • 通过string.format()的%a参数可以对上面的这种格式进行格式化的输出
  • 虽然这种格式很难阅读,但是****这种格式可以保留所有浮点数的精度,并且比十进制的转换速度更快****
print(0x1p-1)						--0.5

print(string.format("%a", 419)) 	  --0x1.a3p+8
 
print(string.format("%a", 0.5))		  --0x1p-1

四、算术运算

  • Lua支持的算术运算有:

    • 加(+)、减(-)、乘(*)、除(/)
    • 取负数(-)
    • 取整除法/floor除法(//)
    • 取模(%)
    • 指数运算
    • 幂运算(^)
  • Lua 5.3引入整型的主要建议是:开发人员要么选择忽略整型和浮点型二者之间的不同,要么就完整地控制每一个数值的表示。因此,****所有的算术操作符不论操作整型值还是浮点型值,结果都是一样的****

  • 整型值和浮点型值之间的算术运算

    • 如果两个操作数都是整型值,则结果也是整型值;否则就是浮点型值

    • 当两个操作数的类型不同时,****运算之前会先将整型值转换为浮点型值****

    • 除法的注意事项

      • 由于两个整数相处并不一定是整数,因此****当两个数进行相除时,interger都会转换为浮点数****(即使两个操作数都是整数液转换)
      • 并且除法运算的结果也是浮点数
    • floor除法

      • floor除法****会对得到的商向负无穷取整,从而保证结果是一个整数****
      • **这样,floor除法就可以与其他算术运算一样遵循同样的规则:**如果操作数都是整型值,那么结果就是整型值,否则就是浮点数类型
      print(3 // 2)		-- 1
       
      print(3.0 // 2)		-- 1.0
       
      print(6 // 2)		-- 3
       
      print(6.0 // 2.0)	-- 3.0
       
      print(-9 // 2)		-- -5
       
      print(1.5 // 0.5)	-- 3.0
      

      取负数运算

      • 返回一个值的负数
      • 使用的时候注意,对要操作的表达式的结果要加上括号,否则有点像是定义一个负数的感觉

      取模运算

      • 取模运算的结果类型与上面介绍的一样,如果两个操作数都是整型值则返回整型;否则返回浮点数
      • 对于实数类型(浮点数)而言,取模运算有一些不同,例如x-x%0.01恰好是x保留2位小数的结果,x-x%0.001恰好是x保留3位小数的结果
      local x = math.pi
       
      print(x - x%0.01)		-- 3.14
       
      print(x - x%0.001)		-- 3.141
      
      • **演示案例:**我们可以使用取模运算检查某辆车在拐过指定的角度后是否能够原路返回。假设使用度作为角度的单位,那么我们可以使用下面的函数
      -- 角度
      local tolerance = 10 
      function isturnback1(angle)
          angle = angle % 360
          return (math.abs(angle - 180) < tolerance)
      end
      print(isturnback1(-180))		-- true
      print(isturnback1(90))			-- false
      
      -- 弧度
      local tolerance = 0.17
      function isturnback2(angle)
          -- 这一条语句实现了将任意范围的角度归一化到[0,2π)之间
          angle = angle % (2*math.pi)
          return (math.abs(angle - math.pi) < tolerance)
      end
      print(isturnback2(-180))		-- false
      print(isturnback2(90))			-- false
      

      幂运算

      • Lua也支持幂运算,使用符号^表示
      • 像除法一样,****幂运算的操作数和结果也永远是浮点类型****(整型类型在幂运算时不能整除)
      • 我们可以****使用x0.5来计算x的平方根,使用x(1/3)来计算x的立方根****

五、关系运算

  • Lua支持的关系运算符如下:
    • 大于(>)、小于(<)
    • 大于等于(>=)、小于等于(<=)
    • 相等(==)
    • 不相等(~=)
  • Lua关系运算的结果都是boolean类型
  • **==、~=说明:**这两个运算符可以应用于任意两个值,当这两个值的类型不同时,Lua语言认为它们是不相等的;否则,会根据它们的类型再对两者进行比较
  • ****比较数值时永远忽略数值的子类型,****数值究竟是以整型还是浮点型表示并无区别,只与算术值有关(尽管如此,比较具有相同子类型的数值时效率更高)
print(1.0 == 1)			-- true
 
print(1 == 1)			-- true
 
print(1.1 == 1)			-- false

六、数学库

  • Lua语言提供了标准数学库math,由一组标准的数学函数组成,包括:

    • 三角函数(sin、cos、tan、asin等):所有三角函数都以弧度为单位,并通过函数deg和rad进行角度和弧度的转换
    • 指数函数
    • 取整函数
    • 最大函数max、最小函数min
    • 用于生成伪随机的伪随机函数(random)
    • 常量pi
    • 常量huge(最大可表示数值,大多大叔平台上代表inf)

    随机数发生器

    • 函数math.random()用于生成伪随机数,一共有三种调用方式
      • 不带参数调用时:函数返回一个在[0,1)范围内的均匀分布的伪随机实数
      • 当使用带有一个整型值n的参数调用时:函数返回一个在[1, n]范围内的伪随机整数
      • 使用两个整型值l和u的参数调用时:函数返回在[l, u]范围内的伪随机整数换
    print(math.random())			-- 0.001251220703125
     
    -- 可以模拟掷骰子的结果
    print(math.random(6))			-- 4
     
    print(math.random(10, 50))		-- 17
    
    • 函数randomseed()用于设置伪随机数发生器的种子,该函数的唯一参数就是数值类型的种子
      • 在一个程序启动时,系统固定使用1为种子初始化伪随机发生器;如果不设置其他的种子,那么每次程序运行时都会生成相同的伪随机数序列
      • 从调试的角度看,这是一个不错的特性,然而,对于一个游戏来说却会导致相同的场景重复不断的出现。为了解决这个问题,**通常调用math.randomseed(os.time())**来使用当前系统时间作为种子初始化随机数发生器(os.time()在后面文章介绍)

    取整函数

    • 数学库提供了三个取整函数:
      • floor:向负无穷取整
      • ceil:向正无穷取整
      • modf:向零取整
    • 当取整的结果能用整数表示时,返回结果为整型值,否则返回浮点型值
    • modf除了返回取整后的值之外,还会返回小数部分作为第二个结果(Lua支持一个函数返回多个值)
    • 如果参数本身是一个整型值,那么它将原样返回
    • 如果想将数值x向最近的整数取整,可以对x+0.5调用floor函数

七、数值类型取值范围

整型取值范围

  • 标准Lua使用64个比特位来存储整型值,其最大值为263-1,约等于109
  • 数学库中的math.maxinteger和math.mininteger常量分别定义了整型值的最大值和最小值
print(math.maxinteger)			-- 9223372036854775807
 
print(math.mininteger)			-- -9223372036854775808
  • **回环:当数值很大或者很小发生溢出时,就会发生回环。回环的意思就是结果只能在maxinteger和mininteger之间,也就是对2^64取模的算术结果。
print(math.maxinteger + 1 == math.mininteger)		-- true
 
print(math.mininteger - 1 == math.maxinteger)		-- true
 
print(-math.mininteger == math.mininteger)			-- true
 
print(math.mininteger // -1 == math.mininteger)		-- true

浮点类型取值范围

  • 对于浮点数而言,标准Lua使用双精度。标准Lua使用64个比特位表示所有数值,其中11位为指数。双精度浮点数可以表示具有大致16个有效十进制位的数,范围从 -10^308 ~ 10^308
  • 双精度浮点数对于大多数实际应用而言是足够大的,但是我们必须了解精度的限制。如果我们使用十位表示一个数,那么1/7会被取整到0.142857142。如果我们使用十位计算1/7*7,结果会是0.999999994而不是1。此外,用十进制表示的有限小数在用二进制表示时可能是无限小数。例如,12.7-20+7.3即便使用双精度表示也不是0,这是由于12.7和7.3的二进制表示不是有限小数
print(12.7-20+7.3)		-- -8.8817841970013e-016
  • 由于整型值和浮点型值的表示范围不同,****因此当超过它们的表示范围时,整型值和浮点型值的算术运算会产生不同的结果:****
print(math.maxinteger + 2)		-- -9223372036854775807
 
print(math.maxinteger + 2.0)	-- 9.2233720368548e+018
  • 上面的结果分析:
    • 第一行对最大可表示整数进行了整型求和,结果发生了回环
    • 第二行对最大可表示整数进行了浮点型求和,结果被取整成了一个近似值。

八、整型值与浮点型值之间的转换

整数转浮点数

  • 我们可以通过将整型值加上0.0将其转换为浮点型:

  • 小于2^53(即9007199254740992)的所有整型值的表示与双精度浮点型值的表示一样,对于绝对值超过了这个值的整型值而言,在将其强制转换为浮点型值时可能导致精度损失

    print(-3 + 0.0)						-- -3.0
     
    print(9007199254740991 + 0.0 == 9007199254740991)	--true
     
    print(9007199254740992 + 0.0 == 9007199254740992)	--true
     
     
    -- 9007199254740992 + 1被取整为9007199254740992,因此不相等
    print(9007199254740993 + 0.0 == 9007199254740993)	--false
    

浮点数转整数

  • **通过与0进行按位或运算,**可以把浮点型值转换为整型值
  • 在将浮点数强制转换为整数时,Lua会检查数值是否与整型值表示完全一致(即没有小数部分且其值在整型值的表示范围内)。如果****不满足条件则会抛出异常****
print(3.0)		--3.0
 
print(3.0 | 0)	-- 3

print(3.0 | 0)	-- 报错
  • 对小数取整必须显式地调用取整函数
  • 另一种把浮点数转换为整型值的方式是使用math.tointeger(),该函数会在输入参数*无法转换为整型值时返回nil***:
print(math.tointeger(-258.0))		-- -258
 
print(math.tointeger(2^30))			-- 1073741824
 
-- 不是整数值
print(math.tointeger(5.01))			-- nil
 
-- 超出范围
print(math.tointeger(2^64))			-- nil

原文链接:https://blog.csdn.net/qq_41453285/article/details/107933437

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值