Why你需要它们吗?帮助您找到问题的高效解决方案的最佳方法是了解问题。您具体需要整数做什么?
我收集到的主要性能损失(当然)是大量的分配。
好吧,你在每个操作上创建闭包,而且我根本不明白为什么你有一个 Double 类,因为 Lua 的数字类型已经是 double 了。你就不能做这样的事吗?
Integer = {}
local function val(o) return type(o) == 'number' and o or o[1] end
function Integer.__add(a,b) return Integer:create(val(a) + val(b)) end
function Integer.__sub(a,b) return Integer:create(val(a) - val(b)) end
function Integer.__div(a,b) return Integer:create(val(a) / val(b)) end
function Integer.__mul(a,b) return Integer:create(val(a) * val(b)) end
function Integer:__tostring() return tostring(self[1]) end
function Integer:create(value)
return setmetatable({math.floor(value)}, Integer)
end
-- test
a = Integer:create(15.34)
b = Integer:create(775.34433)
print((a*10/2+b-3)/3*a+b) --> 5005
有人认为使用自定义 C 实现和用户数据可以做得更好吗?
是的,C 实现应该更快,因为您不需要为每个 Integer 创建一个表;您的用户数据实际上可能只是一个int*
。这也将消除对floor
call.
编辑:我写了一个测试C实现 http://codepad.org/LZpFrKbT它比本文中介绍的 Lua 实现快约 5 倍。
编辑2:到C代码的链接已经死了,所以这是我在硬盘中发现的一些代码,它们可能是也可能不是该链接处的代码。我知道它是针对 Lua 5.1 编译的,但除此之外......不知道它是否是技术上有效的实现。自从我写任何 Lua C 代码以来已经太久了。
#include <math.h>
#include "lua.h"
#include "lauxlib.h"
/* get value of Integer userdata or Lua number at index, or die */
static int checkintX (lua_State *L, int index) {
int result = 0;
if (lua_isuserdata(L, index) && luaL_checkudata(L, index, "integer")) {
result = *(int*)lua_touserdata(L, index);
} else if (lua_isnumber(L, index)) {
double val = lua_tonumber(L, index);
int x = (int) val;
result = (int) lua_tonumber(L, index);
} else {
lua_pushstring(L, "Invalid operand. Expected 'integer' or 'number'");
lua_error(L);
}
return result;
}
static int checkint(lua_State* L, int index) {
int result = checkintX(L, index);
return result;
}
static int create_integer(lua_State* L, int val) {
int* ud = lua_newuserdata(L, sizeof(int));
*ud = val;
luaL_getmetatable(L, "integer");
lua_setmetatable(L, -2);
return 1;
}
static int int_new (lua_State* L) { return create_integer( L, checkint(L,1) ); }
static int int_add (lua_State* L) { return create_integer( L, checkint(L,1) + checkint(L,2) ); }
static int int_sub (lua_State* L) { return create_integer( L, checkint(L,1) - checkint(L,2) ); }
static int int_mul (lua_State* L) { return create_integer( L, checkint(L,1) * checkint(L,2) ); }
static int int_div (lua_State* L) { return create_integer( L, checkint(L,1) / checkint(L,2) ); }
static int int_mod (lua_State* L) { return create_integer( L, checkint(L,1) % checkint(L,2) ); }
static int int_pow (lua_State* L) { return create_integer( L, (int) pow( checkint(L,1), checkint(L,2) ) ); }
static int int_unm (lua_State* L) { return create_integer( L, -checkint(L,1) ); }
static int int_eq (lua_State* L) { lua_pushboolean( L, checkint(L,1) == checkint(L,2) ); return 1; }
static int int_lt (lua_State* L) { lua_pushboolean( L, checkint(L,1) < checkint(L,2) ); return 1; }
static int int_le (lua_State* L) { lua_pushboolean( L, checkint(L,1) <= checkint(L,2) ); return 1; }
static int int_tostring (lua_State* L) {
lua_pushnumber(L, checkint(L,1));
lua_tostring(L, -1);
return 1;
}
int __declspec(dllexport) __cdecl luaopen_integer (lua_State* L) {
static const struct luaL_reg integermt[] = {
{ "__add", int_add },
{ "__sub", int_sub },
{ "__mul", int_mul },
{ "__div", int_div },
{ "__mod", int_mod },
{ "__pow", int_pow },
{ "__unm", int_unm },
{ "__eq", int_eq },
{ "__lt", int_lt },
{ "__le", int_le },
{ "__tostring", int_tostring},
NULL, NULL
};
luaL_newmetatable(L, "integer");
luaL_openlib(L, NULL, integermt, 0);
lua_register(L, "int", int_new);
return 0;
}