4

y=x^2Javascriptのような単純な関数を区別する calc クラスのサイド プロジェクトに取り組んでいます。そのために、式を抽象構文ツリーに解析し、積規則や連鎖規則などの導関数規則をハードコーディングしました。

これに入れられる唯一の関数は、AP 微積分/1 年目の微積分の問題です。そのため、三角関数、対数、指数はすべて有効です。

私のプログラムは導関数を問題なく取りますが、最終的に得られるのは、途方もなく単純化されていない方法で記述された関数です。

たとえば、微分するとx^2が得られます(2*(x^(2-1)))。これは技術的には正しいですが、2*x のように簡単に記述できます。これまでのところ、基本的にツリーを繰り返し分析し、いくつかの基本的なルールを適用する基本的な単純化機能があります。

私が持っている一般的な手順は、再帰降下で分析することです。

現在のツリーに変数がない場合は、それを評価し、現在のノードを結果で置き換えます。

それ以外の場合は、大量の if ステートメントを適用して単純化します。これには次のようなものが含まれます

  • ゼロを掛ける場合は、式をゼロに置き換えます
  • 1 を掛ける場合は、式を他のオペランドに置き換えます
  • 0 乗する場合は、式を 1 に置き換えます。

などなど。似たような用語を組​​み合わせるなど、本当の単純化を実際に行いたい場合、これはすぐに制御不能になります。また、任意の 2 つの式が等しいかどうかを判断したい場合、私が持っている最善の解決策は、単に関数のドメインで乱数を生成し、それらが等しいかどうかを確認することです。ただし、これはあまり効率的ではないようです。

x+22 つの異なる式 (単純な例はand )の等価性をより効率的に判断するに2+xはどうすればよいですか? また、大量の if ステートメントを使用せずに関数を単純化する方法はありますか?

4

2 に答える 2

0

私は、次の一連の手順で問題に対処します。

  1. すべての多項式ノードを「標準的な」方法で書く
    • たとえば、辞書式の順序と次数を使用して単項式を並べ替えます (1 + x常にx + 1などとして表されます)。
  2. すべての有理ノードを「標準的な」方法で書く
    • 有理式は 2 つの多項式の商であるため、ここでは 1 を使用します。
  3. 特定の機能ごとに ID のリストを用意する
    • たとえばln(xy) = ln(x) + ln(y)、 などです。
  4. 単射性の削減のリストを持っている
    • たとえば、またはiffなどの整数値のsin x = sin y場合、およびその場合のみ。x = y + 2*k*Pikln(x) = ln(y)x = y
  5. 等。

これらは、開始するためのいくつかのアイデアにすぎません。プロジェクトは十分に野心的です。

于 2015-12-13T20:02:35.347 に答える
0

私は実際に二分木を使用する計算機代数システムを開発しています。因数分解するために、2 つの式 (ツリー) が数学的に等しいかどうかを判断する比較関数があります。例えば:

  • sin(x+1) + sin(1+x) = 2*sin(x+1)
  • sin(x-1) と sin(1-x) は加算できません
  • x + x^2 = x*(1+x)

アルゴリズムは次のようになります。

各ノードにはサイド (左または右) が割り当てられています。ツリー内の各演算子を検索します。それが + または * の場合、子の辺は関係ありません。ただし、演​​算子が /、^、または - の場合は、子の側面が重要です。除算では、分子に誰が、分母に誰がいます。したがって、このアルゴリズムでは、x+2 は 2+x に等しくなります。

下手な英語でごめんなさい:P

于 2014-08-22T00:02:57.023 に答える