Jump to content
The simFlight Network Forums

Rounding variables in LUA


Recommended Posts

I am working on a lua script to monitor several values from P3D and send them to an Arduino via serial com as strings.  I need the values to be fixed in length in order to interact with existing Arduino code monitoring the com port .  For example, for my bus voltages I have a function to round the values to two decimal places but this removes any trailing zeros.  And of course I loose the leading zero when the voltage drops below 10.

So while 28.3157... results in 28.32 which is what I want, 28.3000 results in 28.3 but I need it to be 28.30  And, on the other side I would need 9.3157 to be 09.32

From what I've read in the lua docs and online I think I should be able to accomplish this with  "string.format()" but I can't seem to make it work and the examples I'm finding aren't helping.

Will string.format accomplish what I need?  If so, what is the correct syntax?  If string.format is not the answer any ideas on how to accomplish this would be greatly appreciated.

Thanks!

Tom G.

Link to comment
Share on other sites

5 hours ago, Scotfleiger said:

The string.format has 2 arguments: a format definition string and the value to format. 

Try string.format("%02.2f", value) for 02.34 or string.format("%.2f", value) for 2.34. 

 

Scott, Thanks!  That takes care of the characters following the decimal.

I'm still dropping the leading character below 10 though.  So, 12.3000... volts shows as 12.30  but 9.3000...  shows as 9.30 not 09.30

Any further thoughts on the integer portion?

Tom G.

Link to comment
Share on other sites

Try "%02d.02f". The 0 means leading zeros, the 2s means two places, the d means decimal and the f means floating points. 

Search also for printf formatting for C and even Delphi formatStr which should give you the meaning of the format codes.

Link to comment
Share on other sites

Scott,

Thanks for pointing me to the syntax references I'm experimenting with various things now.  Still not able to get a leading zero on there via the format function but that may just be my poor programing skills.  I found one delphi reference on how to do it but the syntax does not seem to be supported in lua as it causes the script to fail.

Until I figire it out I am evaluating the varable with an if statement to determine when it goes below 10.00 and if so I am concatenating a leading zero onto the string to be sent.

If you have any other thoughts on this your assistance would be greatly appreciated.  In the interim I'll keep plugging away.

Thanks!

Tom G.

Link to comment
Share on other sites

Hi Tom

The LUA string.format does not appear to be able to handle the decimal point as I thought. I wrote this test function using LINDA LUA editor which I believe achieves what you want:

function test()
    for i = 1, 9999, 1 do
      val = i/100
      val1 = math.floor(i / 100)
      val2 = math.floor((((i / 100) - val1) * 100) + 0.5)

      --ans = string.format("%02d.02d", val)
      --ans = string.format("%02d.%02d", val1, val2)

      ans = string.format("%02d", val1) .. '.' .. string.format("%02d", val2)
      _log('i = ' .. i .. ' ans = ' .. ans .. ' (val1 = ' .. val1 .. ' val2 = ' .. val2 ..  ')')
      ipc.sleep(10)
    end
end

The commented out lines "--ans =" do not work but the following does using val1 as the integer part and val2 and the decimal part:

      ans = string.format("%02d", val1) .. '.' .. string.format("%02d", val2) 

The _log() function is for writing to the LINDA console for debugging purposes. See LINDA Downloads.

Google is a invaluable tool for the programmer. See http://lua-users.org/wiki/StringLibraryTutorial.

Link to comment
Share on other sites

31 minutes ago, Scotfleiger said:

The LUA string.format does not appear to be able to handle the decimal point as I thought.

That is rather odd. Here's the description of the string.format function ffrom the Lua websitr:

string.format (formatstring, ···)

Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). The format string follows the same rules as the ISO C function sprintf. The only differences are that the options/modifiers *, h, L, l, n, and p are not supported and that there is an extra option, q.

The q option formats a string between double quotes, using escape sequences when necessary to ensure that it can safely be read back by the Lua interpreter.

I wonder if it was buggy in version 5.1, which is the one built into FSUIPC (the current release lua version is 5.3).

Pete

 

Link to comment
Share on other sites

Very strange. I must be age. Mine or LUA 5.1 I could not tell.

This statement formats a floating point but the first zero is not used as a filler as Tom requires.

      ans = string.format("%02.02f", val)

For val=1.23 it gives " 1.23" and not "01.23".

Link to comment
Share on other sites

I just looked up the formal definition of the printf, sprintf format string, and there are two relevant parts:

for the 'f' specifier:

Signed value that has the form [-]dddd.dddd, where dddd is one or more decimal digits. The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision, or six by default.

and later, for the 0n prefix:

 

If width is prefixed by 0, leading zeros are added until the minimum width is reached. If both 0 and - appear, the 0 is ignored. If 0 is specified for an integer format (i, u, x, X, o, d) and a precision specification is also present—for example, %04.d—the 0 is ignored.

I checked the source, and the Lua string library does actually use sprintf, the C library function, passing it the complete format string for each component, i.e. %02.02f in the case we are talking about. So it isn't Lua, it is the Microsoft C library. The leading zero business apparently only applies to fixed point formats, like %d.

Because of the wording above I would have thought that &05.2f would give 01.23 in order to make the result 5 characters long. But, no, the 05 makes no difference it seems!

I've been using this stuff for 25+ years. You'd think I would have discovered stuff like this long ago! :-(

Pete

 

 

Link to comment
Share on other sites

If I followed the exchange correctly this is a bug in the C library and the function as designed isn't able to produce the result I need.

But it is possible to evaluate and format the integer portion of the number separate from the decimal portion to get each to a fixed length and then concatenate the result for my output string, yes?

using   ans = string.format("%02d", val1) .. '.' .. string.format("%02d", val2)

I will try this after I get off work today and follow up here to let you know how it works for me.

THANKS!!!

Link to comment
Share on other sites

2 minutes ago, Tom_G_2010 said:

If I followed the exchange correctly this is a bug in the C library

I don't think it's really a bug, just a misunderstanding of the way it works. The description is not as clear as perhaps it should be. as you can see from the extracts I gave.

This works, though: "%05.2f"

So, in your original "%02.02f" there are two bugs: The first 02 tells it the total width should be 2, and you need 5, and the second 02 should just be 2 -- the leading zero there seems to make the first field width specifier null and void.

I think I've always used it correctly in the past -- perhaps more by luck than applying proper knowledge.

Pete

 

 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.