double to int 神奇的 magic number
前段时间写过一篇 blog: _ftol 的优化。 今天在读 lua 5.1 的 source 的时候,发现一个更加有趣的技巧。把 double 转成 int 居然可以这样的简单。
union luai_Cast { double l_d; long l_l; }; #define lua_number2int(i,d) { volatile union luai_Cast u; \ u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
这个宏神奇的在正数和负数的双精度浮点数时都可以正确工作,以四舍五入方式转换为 32 位整数。
这个数字是 1.5*2^52 :) 小于 2^31 的数字在和这个magic number 相加的时候,按浮点加法的规则(以科学计数法记数),和一定按幂大的一个对齐。而 1.5 是2进制的 1.1 在浮点标准中,小数点前的 1 是不需要记录的。这样,double 的前四字节就被空出来。而需要转换的整数将因为加法恰当的被置入对应的位置。
这个技巧并不总是适用,比如初始化 D3D9 以后,就会失效。因为 D3d 默认会调整浮点运算的精度。在低精度模式下,这个技巧显然不能工作。关于这一点的讨论可以参考MSDN 上的一个帖子
Comments
http://blog.codingnow.com/2006/02/double_to_int_magic_number.html#comment-580
Posted by: 我是龙http://blog.codingnow.com/2006/02/double_to_int_magic_number.html#comment-580 | (16) October 11, 2015 10:30 PM
http://blog.codingnow.com/2006/02/double_to_int_magic_number.html#comment-580
Posted by: 我是龙http://blog.codingnow.com/2006/02/double_to_int_magic_number.html#comment-580 | (15) October 11, 2015 10:30 PM
原理为假设一个浮点数1234.56789
IEEE754格式 为1.23456789*10^3
请自动考虑二进制,此处使用十进制演示,并且实际保存是不考虑最前面的1的(二进制后,非0非无穷前面第一位归一化为1)
这样加上这个数值后,强制将最低32位处的内存值保存1234这样的数值(请考虑二进制),然后当作整型取出来就是了,注意不是四舍五入这里
Posted by: hylepo | (14) April 8, 2014 04:57 PM
1.首先这个不是四舍五入的,是取整,floor的操作
2.浮点数要符合IEEE 754的存储标准
3.浮点数的数值不能大于整型值
Posted by: hylepo | (13) April 8, 2014 04:51 PM
#define lua_number2int(i,d) \
{ (i) = (int)((d)+((d>0?0.5:-0.5))); }
这样可以么?
Posted by: 无名 | (12) February 5, 2009 04:24 PM
Very good site. Thank you:-)
http://www.draze.com/search/?search=site%3Anadia.greatnow.com+Alprazolam&type=web&mix=il&eid=3 Buy Alprazolam Online
Posted by: Buy Alprazolam Online | (11) January 7, 2008 04:40 PM
Very good site. Thank you:-)
http://www.draze.com/search/?search=site%3Anadia.greatnow.com+Alprazolam&type=web&mix=il&eid=3 Buy Alprazolam Online
Posted by: Buy Alprazolam Online | (10) January 7, 2008 04:39 PM
赞,如果早点看到这帖,就可以省掉半天的debug。
Posted by: Zwinger | (9) March 16, 2006 09:39 AM
试了一下,好. 还不太懂原理.
发现两点:(Mingw-gcc3.4.2 Win2K)
1. 不能正确舍入
2. double位数不能太大.
1234567890.4
double: 1234567890.400000 int: 1234567890
1234567890.5
double: 1234567890.500000 int: 1234567890
1234567890.6
double: 1234567890.600000 int: 1234567891
123456789012345
double: 123456789012345.000000 int: -2045911175
12345678901234
double: 12345678901234.000000 int: 1942892530
Posted by: sods | (8) March 1, 2006 02:12 PM
今天发现这个技巧在 d3d 下不能用,郁闷了一把。好在 d3d 设备初始化时可以选择控制对浮点状态寄存器的行为。
Posted by: Cloud
| (7)
February 28, 2006 12:19 AM
叹为观止
真的太…………
Posted by: 苏州三 | (6) February 25, 2006 10:34 PM
不是说lua支持16进制了么,把6755399441055744.0变成16进制说不定能理解啊。
Posted by: euclid | (5) February 17, 2006 11:08 AM
游戏编程精粹里面有一本对这个讲得很清楚
Posted by: hehe | (4) February 16, 2006 08:52 AM
Why can it work?
Posted by: Anonymous | (3) February 16, 2006 08:48 AM
俺感觉,想出这个的人一定已经濒死或者梦游。。。
Posted by: 空明流转 | (2) February 15, 2006 11:21 PM
厉害啊!
Posted by: euclid | (1) February 15, 2006 03:25 PM