2010-06-23 557 views

回答

13

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

+7

为了说明起见,Lua具有单个数字数据类型。默认情况下,这是一个'double',但可以在头文件中更改为另一种类型,例如'int64_t'。 – 2010-06-23 19:18:44

+2

如果更改了'luaconf.h'中的数字类型,请不要忘记相应地更改相关的宏。 – lhf 2010-06-23 21:44:40

+0

@lhf:尽管它被记录在宏的上方,但我认为它会很容易被发现。 – Joey 2010-06-23 22:17:47

7
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 
+1

为什么不定义一个具有metatable字段的类来支持算术运算符?为什么没有函数将这些数字转换为十进制字符串(您也可以将此函数绑定到'__string'metatable)? 注意:如果Lua编译为支持带有IEEE 64位双精度的数字,它将精确地存储绝对值<=(2^53)的所有数字。 – 2015-04-19 03:16:50

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。)

+0

是的,这比使用32位整数或字符串数​​组来存储精确值的仿真快得多。然而,Lua也可以很容易地移植到除C或C++之外的其他主机语言(例如,PHP,Java或Javascript)中运行,提供其他本地数字数据类型或更高精度的数字(例如x86体系结构中的80位长双精度) 。 通过仿真,您还可以在Lua中支持复数或矩阵。 – 2015-04-19 03:10:27