Lua是否使用64位整数?

10
Lua是否使用64位整数?如何使用它?
3个回答

14

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


8
Lua有一个数值数据类型。默认情况下,它是“double”类型,但可以在头文件中更改为其他类型,例如“int64_t”。 - Yann Ramin
2
如果您在 luaconf.h 中更改了数字类型,请不要忘记相应地更改相关的宏定义。 - lhf
@lhf:虽然宏的上方有文档说明,但我认为它应该很容易被发现。 - Joey
3
请注意,这将产生一些影响,因为这是数字唯一的类型。例如,对于整数类型的LUA_NUMBER,math.sin不一定是明智的。Lua源代码有一个名为LNUM的补丁,可以通过支持整型和浮点型来缓解此问题。请参见 https://dev59.com/yXNA5IYBdhLWcg3wfNyO#947763。 - RBerteig
我正在制作一个应用程序,用于在PSP上使用PGE Lua游戏引擎。我考虑定义变量的类型,就像在VB.NET或C#中一样。 - Aaron de Windt
2
@Aaron:Lua只有一种数字类型,即使使用RBerteig提到的LNUM补丁,从程序员的角度来看也没有改变-你只是突然拥有了64位整数和双精度浮点数,据我所理解,选择正确的类型将自动完成。在Lua中,你不像VB或C#那样声明类型-这些语言使用完全不同的类型规则。 - Joey

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
为什么不定义一个带有元表字段的类来支持算术运算符?为什么没有将这些数字转换为十进制字符串的函数(您还可以将此函数绑定到“__string”元表)? 注意:如果Lua编译支持IEEE 64位双精度数字,则它会准确地存储所有绝对值<=(2^53)的数字。 - verdy_p

6
Lua 5.3引入了整数子类型,默认使用64位整数。
来自Lua 5.3参考手册

数字类型使用两种内部表示,一种称为整数,另一种称为浮点数。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中支持复数或矩阵。 - verdy_p

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接