https://blog.csdn.net/allenjay11/article/details/53485777
浮点数问题
math.floor(0.57*100)
56
这是浮点数都会有的精度丢失问题,lua也有这个问题。
原因是因为浮点数的再cpu上的表示不同cpu表示不一样的。
而为什么是0.57,而其他很多数没影响呢?
可以看连接:https://zhuanlan.zhihu.com/p/269619376
因此十进制下的0.2无法被精确表示成二进制小数,这也是为什么十进制小数转换成二进制小数时会出现精度损失的情况。
也就是说0.57也是无法精准表示成二进制小数的,在不同平台下截断不一样(这个未验证)
重点:这个如果要验证可以通过
print(string.format("%0.99f", 57/100*100))
不要超过100位,因为stringfomat只支持99.。。太多会报错
打印出来
目前unityeditor下

可以看到具体他在lua中double的具体样子。
BTW,1的表示还是1
也即是说要测试是否有浮点数精度问题,那么通过这个方法打印即可,不然很多其他函数会有四舍五入的情况发生的,就不好验证了。
也就是说如果是lua上看起来是整数的就不会存在精度问题?
其实是对的,但是如果要运算了出现了带小数点的,那么就无法保证了。
下面的代码验证了:
local a = 57
print(math.floor(a/100*100))
结果还是56.。。。
而print(math.floor(a*100/100))
的结果是57就对了。 也就是运算过程中出现了不可表达的浮点数,那么必定会带来精度损失的问题。
再看下整数与浮点数的比较:
=10==10.00000000000000000
true
=10==10.00000000000000001
true
=10==10.00000000000000000
true
=10==9.999999999999999999
true
如何比较两个浮点数是否相等?这里介绍一个方法:
function float_equal(x,v)
local EPSILON = 0.000001
return ((v - EPSILON) < x) and (x <( v + EPSILON))
end
print(float_equal(0.9999999, 1.0000001))
其中,EPSILON就是你允许的精度差
lua整数
在lua5.3之前,lua没有整数,都是用浮点数表示的,最早的版本用float,然后在3.1之后改用double。直到lua5.3,lua才引入了整数,默认是64bit。既然之前的lua版本用到的是浮点数,那必然有精度问题,浮点数需要一部分位来表示指数,double的有效数字是53bit,能表达的最大的有效整数是6755399441055744,而lua5.3能表达的最大整数是 9223372036854775807
至于为什么是6755399441055744,有兴趣的可以看下寂寞同学写的浮点数到整数的快速转换,还有一篇国外的文档 Let's Get to the (Floating)Point
自己案例
装备属性计算的时候,经常会差个1,原因就在于浮点数的精度丢失问题
local MyFloor = function(v)
return math.floor(v + 0.000001)
end

没法判断一个浮点数是不是带小数点后的
local checkhasfloat = function(a)
if math.floor(a) ~= a then
print("not a int:"..string.format("%0.99f", a))
end
end
checkhasfloat(1)
checkhasfloat(0.99999999999)
例如这个就不会打印出来,因为math.floor(0.99999999999) = 1
这就很蛋疼了。
不过可以使用modf
local checkhasfloat = function(a)
local pre, after = math.modf(a)
print("------checkhasfloat------")
print(pre)
end
checkhasfloat(1)
checkhasfloat(0.99999999999)

结果就很完美。
更完善点,判断负数的情况
local checkhasfloat = function(a)
local pre, after = math.modf(a)
print("------checkhasfloat------")
print(pre)
if after > 0 or after < 0 then
print("------has dot after val------")
print(string.format("%0.99f", after))
end
end
checkhasfloat(1)
checkhasfloat(-0.0000000000000001)