数学では文字を含む数式で、積記号(×)の省略が行われますが、これをそのままjavascriptで計算させるとうまくいきません。
そこで、以下のような関数を作りたいのですが、アプローチの仕方だけでも教えてほしいです。
左が引数で右が戻り値です。
- 10k -> 10*k
- 5(3+k) => 5*(3+k)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
こんにちは
以下、ご質問にあるようなプログラムを書くときに、知識としてどのような概念を知っていると、プログラムを書くための糸口になるか、という観点での回答になります。
ご質問にあるような
- 文字列
10k
は、数値の10に変数kを掛ける式 10 × k として解釈される。したがって、k の値として 3 が与えられたら、30 が結果として返される。 - 文字列
5(3+k)
は、数値の5に、数値の3と変数kとを加算した結果を掛ける式 5 × (3 + k ) として解釈される。したがって、k の値として 1 が与えられたら、20 が結果として返される。
という機能のプログラムを書こうとするときに、論理的な拠り所となる基礎概念のひとつとしては、
- wikipedia: 構文木
が思いつきます。また、上記の wikipediaの関連項目として 抽象構文木 がありますが、以下はそこからの引用です。
また、演算子と変数や定数といったオペランドから成る数式などのようなものに対する抽象構文木を例にすると、分枝点は演算子、葉はオペランド(つまり、変数や定数)である。
ご質問にあるようなプログラムは、まさにこの
演算子と変数や定数といったオペランドから成る数式などのようなもの
を作ろうとされていることに他なりません。また、 抽象構文木 の説明には
抽象構文木は、構文解析によって直接得られる具象構文木と、最終的な意味表現などのデータ構造との、中間にあるものと位置付けることができる。(中略)具象に対する構文がたとえばBNFによって規定されるように、・・・
ともありますが、上記の説明に含まれる BNF とは、バッカス・ナウア記法 のことです。バッカス・ナウア記法の説明の冒頭に
バッカス・ナウア記法(英: Backus-Naur form)とは、文脈自由文法を定義するのに用いられるメタ言語のことで、一般にBNFやBN記法と略される。
とあるとおり、文脈自由文法 も、このご質問のような課題を解くプログラムを書こうとするときに関連してくる重要な概念です。
ご質問に
アプローチの仕方だけでも教えてほしいです。
とあったので、整理すると、
- harumakyさんが作ろうとしている、乗算記号を省略した式を計算するプログラムが、正しい式として解釈できる文字列の文脈自由文法を定義する。そのために、BNF記法を用いる。
- 上記の文法によって、
10k
や5(3+k)
は正しい式と解釈される。また、その文法によって、たとえば(5--k)10
の5--k
の部分が正しい式として受け容れられるかが決定される。数学の式だったら、 5-( -k ) とは書くが、5--k と、マイナスを2個続けて書くことはないので、数学の慣例にあわせるのであれば、5--k
は正しい式として認められないような文法となる必要がある。 - 与えられた文字列が、正しい式として受け容れられる文法が決まったら、この文法にそって、与えられた文字列から構文木を生成するプログラム(一般にパーサーと呼ばれます)を実装する。
- 次に、変数の値が与えられたら、パーサーによって生成された構文木にそって四則演算を行い、その結果を算出するようなプログラムを実装する。
コツとしては、初めから、数学で許容されるすべての式を受け容れられるような文法を作って、それの実装を目指すのではなく、まずは、たとえばカッコのない式から始めてみるとか、カッコはあっても、カッコの中にさらにカッコがあることはなく加算と減算のみの式の文法を作って実装してみるなどで、練習をするとよいかと思います。そこから段階的に文法と実装を拡張していくというアプローチがよいかと思います。
補足ですが、上記の説明の中で「文脈自由文法」を挙げましたが、これは形式言語理論に出てくる概念です。ご興味があれば「形式言語理論」でAmazonを検索すると、参考図書がいくつも出てくると思います。書籍のタイトルには「オートマトン」という言葉も入っているものも多いでしょう。
以上、参考になれば幸いです。
投稿2020/06/25 20:39
総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/26 00:45
2020/06/26 05:30
0
こんにちは。
JavaScriptでは、作成した関数を実行するにあたっては、「関数適用」を実行する必要があります。
この「関数適用」は、関数名の後に()
を記述することで実行されます。その際にもし関数に引数を渡す場合は、()
の中に引数を記入します。
(詳細な説明はこちらMDN web docsが参考になるかもしれません。)
例えば、「実数aと実数bの積を求める関数」は以下のように作成、実行します。
javascript
1// 関数の定義(作成) 2const multiple = (a, b) => a * b; 3 4// 関数の実行 5multiple(2, 3); // => 6
また、これらの文法は、JavaScript(ECMAScript)の仕様を管理している団体'tc39'によって定義されており、開発者が自由に変更を加えるには難しい範囲となります。
以上のことから、質問者様の求める形での関数の作成は難しく、可能性はないとは言い切れませんが、実装にはかなり複雑な手段が必要となるかと思われます。
ご事情がわかりませんので何とも言えませんが、代わりに上述のような定義、適用方法を提案させていただきます。
もし、どうしても上記のフォーマットでの記述が必要とのことでしたら、可能か否かは別として、JavaScript以外の言語を検討してみるのもよいかもしれません。
投稿2020/06/25 15:11
総合スコア28
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。