【问题标题】:Does Lua make use of 64-bit integers?Lua 是否使用 64 位整数?
【发布时间】:2011-03-07 11:48:10
【问题描述】:

Lua 是否使用 64 位整数?如何使用它?

【问题讨论】:

    标签: 64-bit types lua integer long-integer


    【解决方案1】:

    自己编译。 Lua 默认使用双精度浮点数。但是,这可以在源中更改(luaconf.h,查找LUA_NUMBER)。

    【讨论】:

    • 澄清一下,Lua 有一个单一的数值数据类型。默认情况下这是一个double,但可以在头文件中更改为另一种类型,例如int64_t
    • 如果更改luaconf.h中的数字类型,别忘了相应地更改相关宏。
    • @lhf:不过,它记录在宏的正上方,所以我认为它很容易被发现。
    • 请注意,这将产生一些广泛的副作用,因为这是唯一的类型数字。例如,math.sin 不一定适用于 LUA_NUMBER 的整数类型。 Lua 源有一个补丁,称为 LNUM 补丁,它可以通过支持整数类型和浮点类型来缓解这种情况。见stackoverflow.com/questions/945731/…
    • @Aaron:只有一个数字类型,即使提到了 LNUM 补丁 RBerteig,从程序员的角度来看也没有改变——你只是突然有了 64 位整数和双精度数和据我了解,选择正确的类型将自动完成。不像在 VB 或 C# 中那样在 Lua 中声明类型——这些语言使用完全不同的类型规则。
    【解决方案2】:
    require "bit"
    
    -- Lua unsigned 64bit emulated bitwises
    -- Slow. But it works.
    
    function i64(v)
     local o = {}; o.l = v; o.h = 0; return o;
    end -- constructor +assign 32-bit value
    
    function i64_ax(h,l)
     local o = {}; o.l = l; o.h = h; return o;
    end -- +assign 64-bit v.as 2 regs
    
    function i64u(x)
     return ( ( (bit.rshift(x,1) * 2) + bit.band(x,1) ) % (0xFFFFFFFF+1));
    end -- keeps [1+0..0xFFFFFFFFF]
    
    function i64_clone(x)
     local o = {}; o.l = x.l; o.h = x.h; return o;
    end -- +assign regs
    
    -- Type conversions
    
    function i64_toInt(a)
      return (a.l + (a.h * (0xFFFFFFFF+1)));
    end -- value=2^53 or even less, so better use a.l value
    
    function i64_toString(a)
      local s1=string.format("%x",a.l);
      local s2=string.format("%x",a.h);
      local s3="0000000000000000";
      s3=string.sub(s3,1,16-string.len(s1))..s1;
      s3=string.sub(s3,1,8-string.len(s2))..s2..string.sub(s3,9);
      return "0x"..string.upper(s3);
    end
    
    -- Bitwise operators (the main functionality)
    
    function i64_and(a,b)
     local o = {}; o.l = i64u( bit.band(a.l, b.l) ); o.h = i64u( bit.band(a.h, b.h) ); return o;
    end
    
    function i64_or(a,b)
     local o = {}; o.l = i64u( bit.bor(a.l, b.l) ); o.h = i64u( bit.bor(a.h, b.h) ); return o;
    end
    
    function i64_xor(a,b)
     local o = {}; o.l = i64u( bit.bxor(a.l, b.l) ); o.h = i64u( bit.bxor(a.h, b.h) ); return o;
    end
    
    function i64_not(a)
     local o = {}; o.l = i64u( bit.bnot(a.l) ); o.h = i64u( bit.bnot(a.h) ); return o;
    end
    
    function i64_neg(a)
     return i64_add( i64_not(a), i64(1) );
    end  -- negative is inverted and incremented by +1
    
    -- Simple Math-functions
    
    -- just to add, not rounded for overflows
    function i64_add(a,b)
     local o = {};
     o.l = a.l + b.l;
     local r = o.l - 0xFFFFFFFF;
     o.h = a.h + b.h;
     if( r>0 ) then
       o.h = o.h + 1;
       o.l = r-1;
     end
     return o;
    end
    
    -- verify a>=b before usage
    function i64_sub(a,b)
      local o = {}
      o.l = a.l - b.l;
      o.h = a.h - b.h;
      if( o.l<0 ) then
        o.h = o.h - 1;
        o.l = o.l + 0xFFFFFFFF+1;
      end
      return o;
    end
    
    -- x n-times
    function i64_by(a,n)
     local o = {};
     o.l = a.l;
     o.h = a.h;
     for i=2, n, 1 do
       o = i64_add(o,a);
     end
     return o;
    end
    -- no divisions   
    
    -- Bit-shifting
    
    function i64_lshift(a,n)
     local o = {};
     if(n==0) then
       o.l=a.l; o.h=a.h;
     else
       if(n<32) then
         o.l= i64u( bit.lshift( a.l, n) ); o.h=i64u( bit.lshift( a.h, n) )+ bit.rshift(a.l, (32-n));
       else
         o.l=0; o.h=i64u( bit.lshift( a.l, (n-32)));
       end
      end
      return o;
    end
    
    function i64_rshift(a,n)
     local o = {};
     if(n==0) then
       o.l=a.l; o.h=a.h;
     else
       if(n<32) then
         o.l= bit.rshift(a.l, n)+i64u( bit.lshift(a.h, (32-n))); o.h=bit.rshift(a.h, n);
       else
         o.l=bit.rshift(a.h, (n-32)); o.h=0;
       end
      end
      return o;
    end
    
    -- Comparisons
    
    function i64_eq(a,b)
     return ((a.h == b.h) and (a.l == b.l));
    end
    
    function i64_ne(a,b)
     return ((a.h ~= b.h) or (a.l ~= b.l));
    end
    
    function i64_gt(a,b)
     return ((a.h > b.h) or ((a.h == b.h) and (a.l >  b.l)));
    end
    
    function i64_ge(a,b)
     return ((a.h > b.h) or ((a.h == b.h) and (a.l >= b.l)));
    end
    
    function i64_lt(a,b)
     return ((a.h < b.h) or ((a.h == b.h) and (a.l <  b.l)));
    end
    
    function i64_le(a,b)
     return ((a.h < b.h) or ((a.h == b.h) and (a.l <= b.l)));
    end
    
    
    -- samples
    a = i64(1);               -- 1
    b = i64_ax(0x1,0);        -- 4294967296 = 2^32
    a = i64_lshift(a,32);     -- now i64_eq(a,b)==true
    print( i64_toInt(b)+1 );  -- 4294967297
    
    X = i64_ax(0x00FFF0FF, 0xFFF0FFFF);
    Y = i64_ax(0x00000FF0, 0xFF0000FF);
    
    -- swap algorithm
    X = i64_xor(X,Y);
    Y = i64_xor(X,Y);
    X = i64_xor(X,Y);
    
    print( "X="..i64_toString(X) ); -- 0x00000FF0FF0000FF
    print( "Y="..i64_toString(Y) ); -- 0x00FFF0FFFFF0FFFF
    

    【讨论】:

    • 为什么不定义一个带有元表字段的类来支持算术运算符?为什么没有将这些数字转换为十进制字符串的函数(您也可以将此函数绑定到“__string”元表)?注意:如果 Lua 被编译为支持 IEEE 64 位双精度数,它会准确存储所有绝对值
    【解决方案3】:

    Lua 5.3 引入了整数子类型,默认使用 64 位整数。

    来自Lua 5.3 reference manual

    类型号使用两种内部表示,一种称为整数,另一种称为浮点。 Lua 有关于何时使用每种表示的明确规则,但它也会根据需要在它们之间自动转换(参见 §3.4.3)。因此,程序员可能会选择主要忽略整数和浮点数之间的差异,或者假设完全控制每个数字的表示。标准 Lua 使用 64 位整数和双精度(64 位)浮点数,但您也可以编译 Lua 使其使用 32 位整数和/或单精度(32 位)浮点数。整数和浮点数均为 32 位的选项对于小型机器和嵌入式系统特别有吸引力。 (参见文件luaconf.h中的宏LUA_32BITS。)

    【讨论】:

    • 是的,这比使用 32 位整数数组或字符串来存储精确值的模拟要快得多。然而,Lua 也可以很容易地移植到 C 或 C++ 以外的其他宿主语言中运行(例如 PHP、Java 或 Javascript),提供其他本机数字数据类型或精度更高的数字(例如 x86 架构中的 80 位长双精度数) .通过仿真,您还可以在 Lua 中支持复数或矩阵。
    猜你喜欢
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 2019-03-25
    • 2010-09-14
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多