2010-06-23 66 views

Trả lời

13

Tự biên dịch. Lua sử dụng số điểm nổi chính xác gấp đôi theo mặc định. Tuy nhiên, điều này có thể được thay đổi trong nguồn (luaconf.h, tìm kiếm LUA_NUMBER).

+7

Để làm rõ, Lua có một kiểu dữ liệu số duy nhất. Theo mặc định, đây là một 'double', nhưng có thể được thay đổi trong các tệp tiêu đề thành kiểu khác, chẳng hạn như' int64_t'. –

+2

Nếu bạn thay đổi kiểu số trong 'luaconf.h', đừng quên thay đổi các macro liên quan tương ứng. – lhf

+0

@ lhf: Mặc dù vậy, tài liệu của nó được ghi lại ngay phía trên macro, vì vậy tôi nghĩ rằng nó có thể được khám phá khá. – 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

Tại sao bạn không định nghĩa một lớp với các trường có thể so sánh để hỗ trợ toán tử arithmeric? Và tại sao không có hàm nào để chuyển đổi các số này sang các chuỗi thập phân (bạn cũng có thể liên kết hàm này với '__string' metatable)? Lưu ý: nếu Lua được biên dịch để hỗ trợ các số có IEEE 64 bit, nó lưu trữ chính xác tất cả các số có giá trị tuyệt đối <= (2^53). –

3

Lua 5.3 giới thiệu loại phụ nguyên, sử dụng số nguyên 64 bit theo mặc định.

Từ Lua 5.3 reference manual

Số loại sử dụng hai cơ quan đại diện bên trong, một gọi là số nguyên và được gọi là phao khác. Lua có các quy tắc rõ ràng về thời điểm mỗi biểu diễn được sử dụng, nhưng nó cũng tự động chuyển đổi giữa chúng khi cần thiết (xem §3.4.3). Do đó, lập trình viên có thể chọn hầu hết bỏ qua sự khác biệt giữa các số nguyên và phao nổi hoặc giả định toàn quyền kiểm soát biểu diễn của từng số. Standard Lua sử dụng các số nguyên 64 bit và phao nổi (64-bit) chính xác, nhưng bạn cũng có thể biên dịch Lua để nó sử dụng các số nguyên 32 bit và/hoặc các số nổi (32-bit) đơn. Tùy chọn với 32 bit cho cả số nguyên và phao nổi đặc biệt hấp dẫn đối với các máy nhỏ và hệ thống nhúng. (Xem macro LUA_32BITS trong tệp luaconf.h.)

+0

Có, điều này nhanh hơn nhiều so với mô phỏng bằng cách sử dụng các mảng số nguyên 32 bit hoặc chuỗi để lưu trữ các giá trị chính xác. Tuy nhiên Lua cũng có thể dễ dàng chuyển sang các ngôn ngữ máy chủ khác so với C hoặc C++ (ví dụ: PHP, Java hoặc Javascript), cung cấp các kiểu dữ liệu số gốc khác hoặc các số có độ chính xác cao hơn (chẳng hạn như 80-bit long double in x86 architectures) . Với mô phỏng, bạn cũng có thể hỗ trợ số phức hoặc ma trận trong Lua. –

Các vấn đề liên quan