4

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?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
RectangleEquals
  • 1,825
  • 2
  • 25
  • 44

1 Answers1

5

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 +(.-) +"))
lhf
  • 70,581
  • 9
  • 108
  • 149
  • Okay, I figured it was just a mathematical race condition of sorts... But this still doesn't explain _why_ it decides to go crazy halfway, and continues onward to infinity. – RectangleEquals May 16 '13 at 12:19
  • 2
    @RectangleEquals, see [The Floating-Point Guide - What Every Programmer Should Know About Floating-Point Arithmetic](http://floating-point-gui.de/). – lhf May 16 '13 at 12:23
  • @RectangleEquals: Note that, while your pattern has nothing to do with this (you could just print out `s` and see the same thing), your pattern is also wrong. You need to escape the `.`, and only check for *one* of them in the second clause: `[%d]+%.?[%d]*`. Otherwise, you could parse "10aaaaa4bdcedd5" just as easily as "10.45". – Nicol Bolas May 16 '13 at 12:25
  • @NicolBolas, you don't need to escape `.` in classes. – lhf May 16 '13 at 12:27
  • @lhf: Sure you do. `.` means to [match any character](http://www.lua.org/manual/5.1/manual.html#5.4.1). If you want to match actual ".", you have to escape it. – Nicol Bolas May 16 '13 at 12:28
  • @NicolBolas, have you tried it? `s="10aaaaa4bdcedd5"; p="[%d]+[.%d+]*"; print(s:match(p))` – lhf May 16 '13 at 12:29
  • @NicolBolas, you need to escape `.` in *patterns* but not in *classes*. OTOH, it does no harm. – lhf May 16 '13 at 12:30
  • 4
    @NicolBolas - 1) In most regex flavors metacharacters `may not` or even `must not` be escaped in classes. 2) I guess, lhf is one of the three men on [that](http://www.lua.org/authors.html) photo, namely, the most intelligent-looking one :-) Do you really want to argue with him about how Lua works? – Egor Skriptunoff May 16 '13 at 13:26
  • @lhf Your example seems to work, and I after a simple `string.format("%3.3f", t)` I can live with the output. Thank you! – RectangleEquals May 16 '13 at 13:37