DX Unified Infrastructure Management

 View Only

New Lua behavior regarding the handling of numbers

  • 1.  New Lua behavior regarding the handling of numbers

    Posted Sep 29, 2022 10:10 AM
    Fundamentally the designers of Lua wrote it such that you did not need to worry about numeric data types. Or maybe more accurately stated, it was written to behave like there was only one representation for numbers regardless of what it might do with them internally. And even more sloppy, that for the most part, if a string looked like a number it could be used as a number without concern.

    That resulted in the supporting of what some used to more traditional languages would consider bad habits.

    You could do something like:
    x = 1 + 2.0
    print(x)

    and you'd get the expected output of 3. 


    No need to worry about the fact that it was written as "integer plus float" - all the conversions necessary to do the math happen under the covers. Then on output you didn't have to worry that the minimal sized output of what should be a floating point value was rendered in an integer format. Mainly because there was no such thing as an "integer" in Lua.

    And

    x="1"
    x=x+2
    print(x)

    and you'd get the expected output of 3 as a number, not a string. 

    No so any more it would appear.

    Now things seem to occasionally pay attention to an implied type.

    If you do
    x = 1
    print(x)

    you get an output of "1"

    If you do
    x = 1.0
    print(x)

    you get an output of "1.0"

    Lua was designed on the idea that 1=1.0 and so there should be no difference in behavior between the two code snippets but now there is. And as a result of this whenever you have to output a numeric value, you have to use printf/sprintf/string.format() in order to get a predictable output. 

    Which leads to the second issue:

     In versions of UIM based on nas 9.34 and older the code

    data = sprintf("DATA:%f~%f~%d~%d", 17922892, 2.1, 3.0, 4.1)
    print(data)

    generates the output
    DATA:17922892.000000~2.100000~3~4

    as expected (17922892 coerced to float, 2.1 is a float, 3.0 rounded to int, 4.1 rounded to int)

    But in nas 9.35 the behavior is different and that code generates an error:
    Error in line 1: bad argument #5 to 'sprintf' (number has no integer representation)

    Interestingly there's no issue converting from int to float for the first two number nor is there an issue converting a float with no decimal value to an int but this code now no longer is able to round 4.1 to 4.

    This uncertainty about whether a value will result in being interpreted as an integer and so work with %d or a float and do generate an error ultimately makes the %d format specifier useless. As a workaround you can use %.0f" instead of "%d" since it appears that casts of int to float always work and the ".0" forces the formatted print to correctly round the floating point number to have no decimal in the display.

    You can also use math.floor() which returns the largest integer smaller than the argument. Problem is that doesn't round and -4.1 results in -5, not -4 as would probably be desired.

    So, I could argue the above two behaviors as defects or not defects but I figured I'd share this since at least the first half of this post has already been raised on another thread as an issue.