Why is lua's string pattern matching doing this? - windows

I have an external application which monitors CPU and GPU temperatures...
I am using Lua with the alien extension to grab these values (via GetWindowText) and to do some pattern matching on these values, effectively extracting the temperature digits out of the string, which by default shows up as something like CPU 67.875 °C...
But perhaps I have the wrong idea on how patterns work in LUA (since they don't appear to be exactly like regex)?
The pattern I am using is [%d]+[.%d+]* which should match any number between 0 and 100.0, correct?
Yet oddly enough, I am getting incredibly strange output when values reach around 56.5 degrees (see link).
Why is this happening?
And how can I extract the correct floating point values (as a string) between 0 and 100 in the format of XYY.ZZZ, where X is not optional, Y is optional, and . is optional unless Z exists?

You're seeing the effect of accumulated rounding errors because 0.16 cannot be precisely represented in floating point. The code below performs better:
local n = 0
while n < 10000 do
local s = tostring(n/100)
local t = s:match("[%d]+[.%d+]*")
print(t)
n = n + 16
end
Now, to your question, try the simpler pattern below:
s="CPU 67.875 °C"
print(s:match("CPU +(.-) +"))

Related

how to limit the amount of digits of a function in Julia

my function has to work with very big numbers, so in order to do that I used parts in my code such as big() . Unfortunately this resulted in giving me a result that is too precise (in other words its slowing the entire code down).
This is how the result looks like.
ΔE = 0.08298347005140644564908076516066986088852555871299296314640532293721884964540988
If possible I would like to limit the result to 4 digits
ΔE = 0.0829
If performance is a concern, probably the best way to do this is with https://github.com/dzhang314/MultiFloats.jl, e.g.
using MultiFloats
x = Float64x4(2.0)
# Calculations performed on x will have Float64x4 precision subsequently...
MultiFloats.jl appears to be the fastest package around at present for such calculations, and will let you choose from precision levels between Float64x2 and Float64x8. In any event, this will be dramatically faster than the BigFloats used in the example above.

Comparing vector of double

I am trying to compare two vectors.
v1 = {0.520974 , 0.438171 , 0.559061}
v2 = [0.520974 , 0.438171 , 0.559061}
I write v1 to a file, read and that's v2. For some reason when I compare the two vectors, I am getting false!
When I do: v1[0]-v2[0] I get 4.3123e-8
Thanks,
Double values, unlike integers, are fragile against write and read. That means, the information that represents them in a string is not necessarily complete.
The leading reason of that is rounding: it's like if you had 1/7 and wanted to write it on a paper in the same format as in your question, you'd get:
0.142857
That's exact to 6 decimal places, but no more than that, and the difference shows up. The only difference in the computer is that it counts in binary (and rounds in binary, too), and is further complicated by the fact that at output (or input) you coerce that into decimal (or back, respectively) and round again at each step. All of those are sources of little errors.
If you want to be able to save and reload your doubles exactly (on the same machine), do it in their native binary representation using a write and read. If you want them to be human-readable, you need to sacrifice the exact reconstruction. You'd then need to compare them up to a little allowed deviation.

Lua string to number parsing speed optimization

I am trying to make a speedtest using Lua as one of the languages and I just wanted some advice on how I could make my code a bit faster if possible. It is important that I do my own speedtest, since I am looking at very specific parameters.
The code is reading from a file which looks something like this, but the numbers are randomly generated and range from 1 zu 1 000 000. There are between 100 and 10 000 numbers in one list:
type
(123,124,364,5867,...)
type
(14224,234646,5686,...)
...
The type is meant for another language, so it can be ignored. I just put this here so you know why I am not parsing every line. This is my Lua code:
incr = 1
for line in io.lines(arg[1]) do
incr = incr +1
if incr % 3 == 0 then
line:gsub('([%d]+),?',function(n)tonumber(n)end)
end
end
Now, the code works and does exactly what I want it to do. This is not about getting it to work, this is simply about speed. I need ideas and advice to make the code work at optimal speed.
Thanks in advance for any answers.
IMHO, this tonumber() benchmarking is rather strange. Most of CPU time would be spent on other tasks (regexp parsing, file reading, ...).
Instead of converting to number and ignoring result it would be more logical to calculate sum of all the numbers in input file:
local gmatch, s = string.gmatch, 0
for line in io.lines(arg[1]) do
for n in gmatch(line, '%d+') do
s = s + n -- converting string to number is automatic here
end
end
print(s)

Double to Int Rounding, Logic Issue

This is more of a puzzle/logic type question, and less of a programming question -- but I was hoping someone could help, because I'm stumped.
I start off with an integer number and need to take X percent of it. Once I get that double number I need to round it back to an integer (Call this Y). It doesn't actually matter if I round it, and I don't really care which way it goes (up or down), so using floor/ceiling would be an acceptable solution -- I just need an int.
Later in the system I will be presented with the int Y, and will need to know what the original number was. At this point if i know what the percentage was, and I know what method i used to get the double to an int -- How can i determine the original number.
This needs to work for every original-number/percentage combination.
Example:
Original number: 997
Percentage: 90
Int-Conversion Method: Floor
997 * .90 = 897.3
floor(897.3) = 897
Y = 897
..
..
Given 897, and knowing the percentage and int-conversion method, how can I determine the original number was 997?
997 * .90 = 897.3
floor(897.3) = 897
Y = 897
Given the method you have suggested, I will explain why returning to the exact number is not possible, given the method and the data you've provided.
Computing the percentage is fine, and you're left with the double value. You then, effectively, truncate some of the data, using the floor function. Truncation is not a bijection, so you can't go back from the 897 -> 897.3, so reproducing the original number is not possible with any degree of certainty. You won't be far wrong, given the scale of the data you've provided, but for larger values, or for situations that require more precision you might find this method to much like guess work.
You would use the formula
original number = calculated number / percentage
Using your numbers
997 = 897 / 0.90
In the original calculation and the reverse calculation, you need to round the answer.
If you don't, you'll be off by one more often when you do the reverse calculation.

Generating random number in a given range in Fortran 77

I am a beginner trying to do some engineering experiments using fortran 77. I am using Force 2.0 compiler and editor. I have the following queries:
How can I generate a random number between a specified range, e.g. if I need to generate a single random number between 3.0 and 10.0, how can I do that?
How can I use the data from a text file to be called in calculations in my program. e.g I have temperature, pressure and humidity values (hourly values for a day, so total 24 values in each text file).
Do I also need to define in the program how many values are there in the text file?
Knuth has released into the public domain sources in both C and FORTRAN for the pseudo-random number generator described in section 3.6 of The Art of Computer Programming.
2nd question:
If your file, for example, looks like:
hour temperature pressure humidity
00 15 101325 60
01 15 101325 60
... 24 of them, for each hour one
this simple program will read it:
implicit none
integer hour, temp, hum
real p
character(80) junkline
open(unit=1, file='name_of_file.dat', status='old')
rewind(1)
read(1,*)junkline
do 10 i=1,24
read(1,*)hour,temp,p,hum
C do something here ...
10 end
close(1)
end
(the indent is a little screwed up, but I don't know how to set it right in this weird environment)
My advice: read up on data types (INTEGER, REAL, CHARACTER), arrays (DIMENSION), input/output (READ, WRITE, OPEN, CLOSE, REWIND), and loops (DO, FOR), and you'll be doing useful stuff in no time.
I never did anything with random numbers, so I cannot help you there, but I think there are some intrinsic functions in fortran for that. I'll check it out, and report tomorrow. As for the 3rd question, I'm not sure what you ment (you don't know how many lines of data you'll be having in a file ? or ?)
You'll want to check your compiler manual for the specific random number generator function, but chances are it generates random numbers between 0 and 1. This is easy to handle - you just scale the interval to be the proper width, then shift it to match the proper starting point: i.e. to map r in [0, 1] to s in [a, b], use s = r*(b-a) + a, where r is the value you got from your random number generator and s is a random value in the range you want.
Idigas's answer covers your second question well - read in data using formatted input, then use them as you would any other variable.
For your third question, you will need to define how many lines there are in the text file only if you want to do something with all of them - if you're looking at reading the line, processing it, then moving on, you can get by without knowing the number of lines ahead of time. However, if you are looking to store all the values in the file (e.g. having arrays of temperature, humidity, and pressure so you can compute vapor pressure statistics), you'll need to set up storage somehow. Typically in FORTRAN 77, this is done by pre-allocating an array of a size larger than you think you'll need, but this can quickly become problematic. Is there any chance of switching to Fortran 90? The updated version has much better facilities for dealing with standardized dynamic memory allocation, not to mention many other advantages. I would strongly recommend using F90 if at all possible - you will make your life much easier.
Another option, depending on the type of processing you're doing, would be to investigate algorithms that use only single passes through data, so you won't need to store everything to compute things like means and standard deviations, for example.
This subroutine generate a random number in fortran 77 between 0 and ifin
where i is the seed; some great number such as 746397923
subroutine rnd001(xi,i,ifin)
integer*4 i,ifin
real*8 xi
i=i*54891
xi=i*2.328306e-10+0.5D00
xi=xi*ifin
return
end
You may modifies in order to take a certain range.

Resources