1

コロナアプリで数学の文字列を評価したいと思います。現在、私は三角関数に焦点を合わせているので、例を私たちが直面する可能性が最も高いものにしましょう:

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

私の目標は、これをどういうわけか(どちらか)pi --> math.piスイッチを使ってそのまま評価すること、あるいはそれを分割することです。ただし、上記のように複雑になる可能性があるため、分割ははるかに困難になりますが、単にsin(1)

ですから、Python関数にできるだけ近づけたいと思いeval(expr)ますが、それができない場合は、柔軟性があります。

4

2 に答える 2

0

sin最も簡単な方法は、math.sin(など)に置き換え、欠落pimath.piている乗算記号を追加し、それを実行することloadstringですloadstringが、コロナ環境では使用できません。

これは、これらの式に対して独自のパーサーを作成する必要があることを意味します。出発点として役立つかもしれないコロナフォーラムでの議論を見つけました:ここに、いくつかの詳細とデモがここにあります

于 2012-09-24T15:44:20.947 に答える
0

これでうまくいくはずです。「math.function」を入力せずにluamath関数を使用できるため、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
于 2016-10-30T21:30:57.367 に答える