While working on an update of my bit32 module, I’ve been wondering if it is possible to make a type that accepts numbers between the int32 range. (0 -> 4,294,967,295)
. If any float, negative, or number above 4,294,967,295
is added, it would not show as compatible.
I don’t see why not, just follow this t’ing down here with your preference:
Hey, thanks for the resource but unfortunately it won’t really work for what I’m trying. But I’ll try what I can and update you on it.
Ok my b , I’ll try to respond the best I can.
i guess you can just do if statements?
if 0 < val < 4294967295 then warn("Not compatiable") end
Yeah that is sort of what I am trying to do. My idea is that I can make an Int32 custom type with a function like int32.new()
and then narrow the inputs to only include the 4 bytes of information, incoded in utf8.
local function ToInt(value)
return math.floor(value % 4294967296)
end
print(ToInt(28374.3458745)) -- 28374
print(ToInt(4294967298)) -- 2
this will not make a real int it will still be stored in memory as a double and consume the same amount of memory as a double the CPU will still compute it like a double
Alright. Since it can’t be stored as a single int, I might as well combine 2 ints into a float to maximize efficiency.
Edit: Forgot to mention there is a way to store a ‘single int’, although under utf8 incodement.
function li32.pack(n:number): int32
return {['v']=utf8.char(extr(n,0,8),extr(n,8,8),extr(n,16,8),extr(n,24,8))}
end
CPU’s are very efficient working with doubles if you like you can use bitwise operations to store multiple values in a single variable while it will use less ram it wont be as fast as using the double directly
Not much need for bit32 in this case to combine two int32s, as bit32 can’t work for floats. There is an easier way to do this however:
tonumber(int32..'.'..int32:reverse())
, in this way both int32s would remain intact as a double.
Edit: even more than 2 int32’s can be added since doubles have more than 2^32-1 of ‘int’ space.
this is a string the way strings work is each character uses 1 byte
so something like
728354.34534534 would use 15 bytes plus anything lua stores behind the scenes like the string length that could be saved as a int but i have not looked into the source code of lua strings
and strings are character arrays so they will be a lot slower then using doubles directly
yes, I am aware of that and it’s why I added tonumber
.
Strange, since utf8 has 2^30-1
different characters, that would mean it is 20 bits (2.5 bytes)
kind of strange to convert 2 numbers into a character array then back to a number
also you need to be careful with precision errors Programming in Lua : 2.3
so im not 100% sure but you might get precision errors at values like 4294967295.4294967295
the first 128 characters use 1 byte then it will go up to 2 bytes and 3 bytes and so on
here is how to use bitwise
-- the 2 numbers we want to save
local value1 = 123
local value2 = 46346
-- save both numbers into a single variable (double)
local save = bit32.replace(value1, value2, 16, 16)
-- extract the 2 values back from the single variable (double)
local loadedValue1 = bit32.extract(save, 0, 16)
local loadedValue2 = bit32.extract(save, 16, 16)
-- print the 2 values
print(loadedValue1)
print(loadedValue2)
because bit32 only gives us 32 bits we can split it into 16,16
so that would give us a max value range of 0 to 65535 but if you like you can split it any way you like for instance 8, 8, 8, 8
or 20, 12
bitwise operations are very fast but still not as fast as using the double directly
Yes, I know how to use bitwise. I made a public resource on it.
Also something’s up with converting utf8 back to its numeric form, and I don’t know why.
I used this code:
local s = {}
local miscal = 0
for c=1, 1048575 do
s[#s+1] = utf8.char(c)
end
local str = table.concat(s,'')
for i, v in pairs(s) do
if not utf8.codepoint(str:sub(i)) == v then
miscal+=1
end
end
print(miscal)
And it errored, suggesting that not all utf8s can be converted back
in this video I show how to convert numbers into base 90
so you could store 65610000 values just using 4 characters in a string
or 5904900000 values with just 5 characters
the reason I use base 90 is because there are only 94 characters that you can save into the datastore that consume only 1 character
the 4 characters that are missing are - , space delete
but i use - to indicate negative numbers and , to split numbers and I left out white space characters
doubles use 8 bytes and according to Lua object memory sizes | WoWWiki | Fandom strings use 24 + length bytes so using 2 separate number variables would use less memory then a empty string
local Int32 = {}
function Int32.new(Value)
local Int = {}
setmetatable(Int, {__index = Int32})
Int.Value = if Value < -4294967295 or Value > 4294967295 then 0 elseif Value > -4294967295 and Value < 0 then math.abs(math.floor(Value)) elseif Value > 0 and Value < 4294967296 then math.floor(Value) else 0
return Int
end
local Int = Int32.new(10)
print(Int.Value) --10
local Int2 = Int32.new(20.32)
print(Int2.Value) --20
local Int3 = Int32.new(-1)
print(Int3.Value) --1