Page 1 of 1

Round-function

Posted: Saturday 27 June 2020 16:16
by Toulon7559
To get rid of too many decimal digits a Round-function is useful.
Till recently the 2 lua-functions below helped me

Code: Select all

local function Round(num, idp)
    return tonumber(string.format("%." ..(idp or 0).. "f", num))
end

function round(num, dec)
   if num == 0 then
     return 0
   else
     local mult = 10^(dec or 0)
     return math.floor(num * mult + 0.5) / mult
   end
end
As part of a recent fresh install of a RPI3B+ with latest Raspian_Buster + latest Domoticz-stable I shifted a number of error-free scripts from another RPI to the new configuration.

Now these scripts react differently.
For the fresh install the Round-functions get confronted with num = nil => error-report
Obviously a nil-check should proceed the calling of the Round-function, but in the fresh install that does not happen for unknown reasons.

If calling the Round-function with a valid value num, for idp=0 or for dec=0 still 1 decimal appears.
Checking with slightly earlier versions of Buster+Domoticz, the same effect visible for the decimals.

Somebody knowing a solution?
Something related with the upgrade of lua?

Re: Round-function

Posted: Saturday 27 June 2020 16:41
by jvdz
The Round function will also trigger an error in an old setup when num=nil.
You could avoid that by doing something like this:

Code: Select all

function Round(num, dec)
	return tonumber(string.format("%." ..(dec or 0).. "f", num or 0))
end
Edit: Just tested with this simple script in the build-in LUA script editor on an Buster/Domoticz 2020.2 test setup:

Code: Select all

commandArray = {}

function Round(num, dec)
	return tonumber(string.format("%." ..(dec or 0).. "f", num or 0))
end

print(Round(nil,nil))
print(Round(nil,0))
print(Round(0,nil))
print(Round(1.12345,0))
print(Round(1.14345,1))
print(Round(1.16345,1))

return commandArray

Output:

Code: Select all

 2020-06-27 17:50:00.166 Status: LUA: 0
2020-06-27 17:50:00.166 Status: LUA: 0
2020-06-27 17:50:00.166 Status: LUA: 0
2020-06-27 17:50:00.166 Status: LUA: 1
2020-06-27 17:50:00.166 Status: LUA: 1.1
2020-06-27 17:50:00.166 Status: LUA: 1.2 
So all looks correct. Do you have some simple test script that fails for you so I can test?
Jos

Re: Round-function

Posted: Saturday 27 June 2020 18:52
by Toulon7559
This is a script example which for unknown reasons gets 1 decimal in the uploadstring towards an ESP8266-with-OLED:
the round-function is the extended version in my earlier message.
Comparing with other scripts nothing strange.

Code: Select all

sPwr2, sEnergy2 = otherdevices_svalues[Consumption]:match("([^;]+);([^;]+)")
sPwr2 = round(tonumber(sPwr2),0)
print ('Pwr2 = '.. sPwr2)
-- sEnergy2 = round(tonumber(sEnergy2),0);
-- print ('Energy2 = '.. sEnergy2)
if sPwr2 > 999 then
   UploadURL2 = baseurl .. ",6,1,In=".. sPwr2 .."W"
else 
   UploadURL2 = baseurl .. ",6,1,Vb=0".. sPwr2 .."W" 
end
if sPwr2 <100 then
   UploadURL2 = baseurl .. ",6,1,Vb=00".. sPwr2 .."W"
end
print (UploadURL2)
Will try your variation on the short formula and see what happens.

Added after testing:
Correct operation with Round1 instead of round with Round1 as below

Code: Select all

function Round1(num, dec)
	return tonumber(string.format("%." ..(dec or 0).. "f", num or 0))
end

Re: Round-function

Posted: Saturday 27 June 2020 19:01
by jvdz
in this script you have round() in stead of Round(), so do you have 2 different functions as LUA is case sensitive?

Jos

Re: Round-function

Posted: Saturday 27 June 2020 19:26
by Toulon7559
@jvdz

Correct!
Have corrected my previous message to point to the applicable Round1-function.
Result of application of your variation in the example script: correct rounding!
Thanks!

Re: Round-function

Posted: Saturday 27 June 2020 19:50
by waaren
Toulon7559 wrote: Saturday 27 June 2020 19:26 Correct,
Have corrected my previous message to point to the applicable Round1-function.
The Lua round function as used in dzVents:

Code: Select all

function round(value, decimals)
	local nVal = tonumber(value)
	local nDec = ( decimals == nil and 0 ) or tonumber(decimals)
	if nVal >= 0 and nDec > 0 then
		return math.floor( (nVal * 10 ^ nDec) + 0.5) / (10 ^ nDec)
	elseif nVal >=0 then
		return math.floor(nVal + 0.5)
	elseif nDec and nDec > 0 then
		return math.ceil ( (nVal * 10 ^ nDec) - 0.5) / (10 ^ nDec)
	else
		return math.ceil(nVal - 0.5)
	end
end