【问题标题】:Evaluating a math string in Corona Lua在 Corona Lua 中评估数学字符串
【发布时间】:2012-09-16 02:06:58
【问题描述】:

我想在我的电晕应用程序中评估一个数学字符串。现在我专注于三角函数,所以让我们让这个例子成为我们可能面临的最困难的例子:

local expr = "2sin(4pi+2)+7"

我的目标是通过pi --> math.pi 开关以某种方式(或者)对其进行评估,或者甚至将其分解。然而,分手会更加困难,因为它可能和上面一样复杂,但也可能只是sin(1)

所以我宁愿尽可能靠近 python eval(expr) 函数,但如果这不能发生,我很灵活。

【问题讨论】:

    标签: lua coronasdk


    【解决方案1】:

    最简单的方法是将sin 替换为math.sinpi 替换为math.pi 等等),添加缺少的乘法符号,然后运行loadstring,但loadstring 不可用在电晕环境中。

    这意味着您需要为这些表达式编写自己的解析器。我在 Corona 论坛上找到了一个可以帮助您作为起点的讨论:here,其中包含一些详细信息和演示 here

    【讨论】:

    • Jack Crenshaw 写了一篇很棒的关于如何编写表达式解析器的教程:compilers.iecc.com/crenshaw 虽然它已经很老了,但我发现它很有帮助,而且不太复杂......
    【解决方案2】:

    这应该可以解决问题,它能够使用 lua 数学函数而无需放置“math.function”,因此 sqrt(100) 可以正常工作。我把它放在一起是因为我已经看到这个问题被问了太多次了。希望这会有所帮助:)

    如果您有任何问题,请随时通过 rayaman99@gmail.com 与我联系

    function evaluate(cmd,v) -- this uses recursion to solve math equations
        --[[ We break it into pieces and solve tiny pieces at a time then put them back together
            Example of whats going on
            Lets say we have "5+5+5+5+5"
            First we get this:
            5+5+5+5 +   5
            5+5+5   +   5
            5+5 +   5
            5   +   5
            Take all the single 5's and do their opperation which is addition in this case and get 25 as our answer
            if you want to visually see this with a custom expression, uncomment the code below that says '--print(l,o,r)'
        ]]
        v=v or 0
        local count=0
        local function helper(o,v,r)-- a local helper function to speed things up and keep the code smaller
            if type(v)=="string" then
                if v:find("%D") then
                    v=tonumber(math[v]) or tonumber(_G[v]) -- This section allows global variables and variables from math to be used feel free to add your own enviroments
                end
            end
            if type(r)=="string" then
                if r:find("%D") then
                    r=tonumber(math[r]) or tonumber(_G[r]) -- A mirror from above but this affects the other side of the equation
                    -- Think about it as '5+a' and 'a+5' This mirror allows me to tackle both sides of the expression
                end
            end
            local r=tonumber(r) or 0
            if o=="+" then -- where we handle different math opperators
                return r+v
            elseif o=="-" then
                return r-v
            elseif o=="/" then
                return r/v
            elseif o=="*" then
                return r*v
            elseif o=="^" then
                return r^v
            end
        end
        for i,v in pairs(math) do
            cmd=cmd:gsub(i.."(%b())",function(a)
                a=a:sub(2,-2)
                if a:sub(1,1)=="-" then
                    a="0"..a
                end
                return v(evaluate(a))
            end)
        end
        cmd=cmd:gsub("%b()",function(a)
            return evaluate(a:sub(2,-2))
        end)
        for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/])(.*)") do -- iteration this breaks the expression into managable parts, when adding pieces into
            --print(":",l,o,r) -- uncomment this to see how it does its thing
            count=count+1 -- keep track for certain conditions
            if l:find("[%+%^%-%*/]") then -- if I find that  the lefthand side of the expression contains lets keep breaking it apart
                v=helper(o,r,evaluate(l,v))-- evaluate again and do the helper function
            else
                if count==1 then
                    v=helper(o,r,l) -- Case where an expression contains one mathematical opperator
                end
            end
        end
        if count==0 then return (tonumber(cmd) or tonumber(math[cmd]) or tonumber(_G[cmd])) end
        -- you can add your own enviroments as well... I use math and _G
        return v
    end
    a=5
    print(evaluate("2+2+2*2")) -- This still has work when it comes to pemdas; however, the use parentheses can order things!
    print(evaluate("2+2+(2*2)"))-- <-- As seen here
    print(evaluate("sqrt(100)"))
    print(evaluate("sqrt(100)+abs(-100)"))
    print(evaluate("sqrt(100+44)"))
    print(evaluate("sqrt(100+44)/2"))
    print(evaluate("5^2"))
    print(evaluate("a")) -- that we stored above
    print(evaluate("pi")) -- math.pi
    print(evaluate("pi*2")) -- math.pi
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-29
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多