今天把项目中所有使用的脚本从python替换到lua,一切看起来很美,不过最后测试的时候发现一个非常诡异的问题,具体lua语句如下:
print("simple test: ")
print((10000 + 123456789) - 123456789)
程序打印出来的值竟然是10003,顿时被雷到了。虽然我知道lua用的是double作为基础的lua_number,但是人家已经很耐心的教育我们double是双精度类型,不会出现什么四舍五入的问题。于是打开linux上的终端运行lua进行同样的计算,这次得到的是正确的结果:10000。
想想也知道lua不会有这种低级的错误的,要不还不立刻被人骂死,于是开始找自己的问题,首先怀疑是我们的lua嵌入包裹代码的问题,仔细review了一遍代码,觉得不会影响到这么底层的问题。接着开始做实验,发现在服务器上的同样lua代码,运行的结果是正确的。经过无尽的折腾,最后发现了这么一个事实:
在directX的sdk文档里面,D3DCREATE这个条目里面有这么一条:
D3DCREATE_FPU_PRESERVE Set the precision for Direct3D floating-point calculations to the precision used by the calling thread. If you do not specify this flag, Direct3D defaults to single-precision round-to-nearest mode for two reasons:
- Double-precision mode will reduce Direct3D performance.
- Portions of Direct3D assume floating-point unit exceptions are masked; unmasking these exceptions may result in undefined behavior
D3D默认在创建设备的时候,会把双精度改成单精度,增加渲染的效率,所以lua也被殃及了,这也算是蝴蝶效应的一个体现吧。。。。。
恶心的问题只要原因找到了解决总是相对容易的,现在有两个方案:
- 将lua_number定义为int,缺点是lua内就不能使用小数
- 在D3D初始化的时候添加参数,让他不要改变计算精度,缺点是不知道对性能有多大影响
其实对于UI的话,完全可以定义成整形,呵呵。不过别人用UI做计算就郁闷了
Link | February 4th, 2010 at 19:18