Lua 5.3 and Integers

When playing with some code earlier I noticed a bit of an oddity with some numbers.

function setup()
   A = 0
end

function draw()

    A = A + 0.0125
    B = A // 1
    C = math.floor(A)
        
    fill(255); textMode(CORNER)
    text(type(A).." = "..A,150,700)
    text(type(B).." = "..B,150,680)
    text(type(C).." = "..C,150,660)
end

A obviously outputs as a float, whilst B is displayed as “n.0” and C is just displayed as “n”.

I’m not bothered about the output - I know that can be controlled via string.format(), but I was curious as to whether B is actually a true integer.

Turns out in this example you could pass B as a parameter to a function like image.get() (which will fail if you pass A ) or is it due to the fact that B has no fractional part and can therefore be internally converted into an integer.

So it looks like using the new integer divider operator (//) might work as a quick way to floor a value - the question is, is it a faster / cleaner way than using math.floor (or a local reference to math.floor)?

@TechDojo I’ll let you decide which is faster. Run this and see the time it takes to run a 10,000,000 loop. Comment one and uncomment the other.

function draw()
    background(0)
    t=os.clock()
    for z=1,10000000 do
        --a=5.432//1
        a=math.floor(5.432)
    end
    print(os.clock()-t)
end

That is actually a huge difference, thanks for sharing @dave1707! 4 seconds for me.

@TheSolderKing Unless you’re writing time sensitive code, I don’t think it really matters which one is used. I’m sure there’s going to be other code in a program that could slow a program down more. Unless you try different statements and time each one, you’ll have slowdowns.

another test (more fair bacause math.floor is copied locally)

-- test speed integer

function setup()
    t1 = test1()
    t2 = test2()
    print("speed increase x"..string.format("%1.1f",t1/t2))
    -- typical result speed increase x3.6
end
function test1()
    t=os.clock()
    local f = math.floor
    local a
    for z=1,10000000 do
        a=f(5.432)
    end
    t = os.clock()-t
    print("local math.floor: ".. tostring(t) )
    return t
end
function test2()
    t=os.clock()
    local f = math.floor
    local a
    for z=1,10000000 do
        a=5.432//1
    end
    t = os.clock()-t
    print("integer division: ".. tostring(t) )
    return t
end

@Jmv38 In test1() you set local f=math.floor, but you still called math.floor instead of f in the for loop.

ooops! corrected

@TechDojo the type function will give you the general type of numbers (i.e., it will give you number for all numbers). If you want to see the specific type of number use math.type( n ), which returns float for A and B in your example, but integer for C (because math.floor returns an integer)

@Simeon - thanks for clarifying that. However I found this online

from http://www.inf.puc-rio.br/~roberto/talks/ws2014.pdf

? Integer division converts operands to integers
and does an integer division

Also these references
http://lua.2524044.n2.nabble.com/5-3-Converting-a-floating-point-number-to-integer-td7664081.htmlhttp://lua-users.org/lists/lua-l/2014-11/msg00221.html

I would have thought therefore that math.type(B) would also have been an integer - but I guess the proof of the pudding etc…

Interestingly

B = (A // 1) | 0
print(math.type(B)) -- "Integer"

The reason I was investigating this is because now that bitwise operations are available I wanted to port over some animation code I wrote a while back that allows for things like triggering events on a given frame where individual frames in the animation can have some of the top bit’s set to represent various flags.

I’m wondering also if this will open a whole new “integer only” sub section of Lua where like the emscriptem library for Javascript, if you force values to be integer and then stick to integer math will that give a significant speed increase on calculations?

@TechDojo performance would probably come down to the hardware. On older iOS devices there was a definite performance benefit to integers (and 32 bit floats instead of 64 bit doubles). But with arm64 I probably wouldn’t pursue integers for performance reasons.

Integer division converts operands to integers and does an integer division

It converts the operands to integers, the return type appears to be dependent on the types of the operands:

integer // integer -- return type is integer
integer // float -- return type is float
float // float -- return type is float

This makes sense because if you’re using floats within an integer division you’re likely using the result of that expression with more floating point values, so it avoids the need of a floatintegerfloat conversion.

@Simeon - makes sense, an interesting diversion all the same :slight_smile:
Thanks for your help

Actually I have a question about the Goto keyword? What is it for and why use it? I can’t figure it out.

@Progrmr235 If you don’t know what it’s for and you don’t know why/how to use it, then you really don’t need it. It’s a way to jump around within a function using “if” statements. If you start using goto’s, it can make your code harder to modify as you add more and more code. If you’ve never used a goto statement, then don’t start now.

seeing goto makes me feel nostalgic for the days of BASIC…

who remembers when you had to give each instruction a line number and enter them in strict sequential order?

I remember basic on my Apple II when the variable names could be only 2 letters long.

Yes! Same on the Dragon 32. I still catch myself using 2 letter variables

@Progrmr235 - the main use of the Goto function is expected to be where you have nested for loops, and you are in the middle somewhere and want to break out of all of them. The break command only breaks out of the loop you are in, so until now, you had to set a variable to true and test for it in each of the nested loops, if you wanted to break out of several loops at once. Now you can just Goto a line that is beyond the end of all the loops.

@yojimbo2000 - i hated compulsory line numbers. I used to leave gaps of 10 to start with, and inevitably, that would not be enough in places. Those were the days when graphics meant using the pset command to colour one pixel at a time!

Yup yup, gaps of 10, I remember that. I think my main use of goto back then was when you realised you needed to insert a bunch of code inbetween, say lines 50 and 60, so you’d have to put 55 GOTO 1000 or whatever.

Thanks guys