How can I match floating point numbers like 1.234
or that use the "E notation" like 1.23e04
when dealing with strings?
As an example, let's say that I would like to read numbers from a data file like the following:
0.0 1.295e-03
0.1 1.276e-03
0.2 1.261e-03
0.3 1.247e-03
0.4 1.232e-03
0.5 1.218e-03
At the moment I wrote my own function to convert each line in the numbers it contains, but it's not very elegant and not portable at all: data files with a different "layout" will give errors.
Here is a simple example that reads the data file already presented and prints to screen the numbers:
function read_line(str)
local a, b, c, d, e = str:match(
"^%s*(%d+)%.(%d+)%s+(%d+)%.(%d+)[Ee]%-*(%d+)")
if str:match("%-") then
e = -tonumber(e)
end
local v1 = a + .1*b
local v2 = (c + .001*d) * 10^e
return v1, v2
end
for line in io.lines("data.txt") do
print(read_line(line))
end
and this gives as a result:
0 0.001295
0.1 0.001276
0.2 0.001261
0.3 0.001247
0.4 0.001232
0.5 0.001218
This is indeed the result I want to achieve, but is there a more elegant and general way to deal with this problem?
Note: Data files can have more than two columns of numbers and can have both the floating point representation and the "E notation".
Assuming every line contains only whitespace separated numbers, you can let tonumber
do the heavy work instead of matching numbers manually:
function split_number(str)
local t = {}
for n in str:gmatch("%S+") do
table.insert(t, tonumber(n))
end
return table.unpack(t)
end
for line in io.lines("data.txt") do
print(split_number(line))
end
Lua can read numbers directly:
f=assert(io.open("data.txt"))
while true do
local a,b=f:read("*n","*n")
if b==nil then break end
print(a,b)
end
f:close()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With