質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

4回答

4336閲覧

JavaScriptで取得した式を計算したい(四則演算のみ)

ko20vonobird

総合スコア50

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2017/01/05 14:26

編集2017/01/06 01:34

###前提・実現したいこと

HTMLのフォームから「式」を取得し、四則演算記号を判別して演算の順番通りに計算をこなしていくということを実現したいです。 仕組みとしては、四則演算子を一つずつ潰していく感じになります。今対応させるのは自然数のみです。 最終的に結果が全て計算されたものになるようなプログラムを目指しています。

###発生している問題・エラーメッセージ

乗除計算では値が不自然なものに、和と差の計算では結果に"NaN"が含まれかつ式も右にそのまま出てきます。 三項以上の掛け算でNaNが出現します。

###該当のソースコード

JavaScript

1function keisan() { //a 2 /*try{*/ 3 var chk1 = 0 4 var str = document.siki.mainsiki.value; 5 var strlong = str.length; 6 for (var cnt = 0; cnt < 10; cnt++) { //b 7 if (str.indexOf(cnt, 0) != 0) { //c 8 chk1++ 9 } //c 10 } //b 11 if (chk1 > 9) { //d 12 alert("最初の文字は数字にしてください"); 13 return; 14 } //d 15 var siki = str; 16 var sikilong = siki.length; 17 var sisoku = new Array(); 18 sisoku[0] = '+'; 19 sisoku[1] = '-'; 20 sisoku[2] = '*'; 21 sisoku[3] = '/'; 22 var sisokunum = 0; 23 for (var cntstrnum = 0; cntstrnum < sikilong; cntstrnum++) { //e 24 var chk = siki.charAt(cntstrnum); 25 for (var cnta = 0; cnta < 4; cnta++) { //f 26 if (chk == sisoku[cnta]) { //g 27 sisokunum = sisokunum + 1; 28 } //g 29 } //f 30 } //e 31 if (sisokunum == 0) { //h 32 alert("答え:" + siki); 33 return; 34 } //h 35 //×÷の計算 36 var nisokukw = 0; 37 for (var cntnuma = 0; cntnuma < sikilong; cntnuma++) { //1 38 var chk = siki.charAt(cntnuma); 39 for (var cntb = 2; cntb < 4; cntb++) { //2 40 if (chk == sisoku[cntb]) { //3 41 nisokukw = nisokukw + 1; 42 } //3 43 } //2 44 } //1 45 var kakerupo = -1; 46 var warupo = -1; 47 for (var cntmaina = 0; cntmaina <= nisokukw; cntmaina++) { //4 48 for (var cntc = 2; cntc < 4; cntc++) { //5 49 if (siki.indexOf(sisoku[cntc]) != -1) { //6 50 if (cntc == 2) { //7 51 kakerupo = siki.indexOf(sisoku[cntc]); 52 } else if (cntc == 3) { //7 53 warupo = siki.indexOf(sisoku[cntc]); 54 } //7 55 } //6 56 } //5 57 if (kakerupo == -1 && warupo == -1) { 58 break; 59 } 60 if (kakerupo != -1 && warupo != -1) { //8 61 if (kakerupo > warupo) { //9 62 var levelrl = kakerupo; 63 } else { //9 64 var levelrl = warupo; 65 } //9 66 } else if (kakerupo != -1) { //8 67 var levelrl = kakerupo; 68 } else if (warupo != -1) { //8 69 var levelrl = warupo; 70 } //8 71 var levelll = -1; 72 for (var cntd = levelrl - 1; cntd >= 0; cntd--) { //i 73 if (levelll != -1) { //j 74 break; 75 } //j 76 for (var cntnumb = 0; cntnumb < 4; cntnumb++) { //k 77 if (siki.charAt(cntd) == sisoku[cntnumb]) { //l 78 var levelll = cntd; 79 break; 80 } //l 81 if (levelll != -1) { //m 82 break; 83 } //m 84 } //k 85 } //i 86 if (levelll == -1) { //n 87 levelll = 0; 88 } //n 89 a = siki.substring(levelll, levelrl - 1); 90 sikipa = siki.substring(0, levelll); 91 var levellr = levelrl; 92 var levelrr = -1; 93 for (var cnte = levellr + 1; cnte < sikilong; cnte++) { //o 94 for (var cntnumc = 0; cntnumc < 4; cntnumc++) { //p 95 if (siki.charAt(cnte) == sisoku[cntnumc]) { //q 96 levelrr = siki.charAt(cnte); 97 break; 98 } //q 99 if (levelrr != -1) { //r 100 break; 101 } //r 102 } //p 103 if (levelrr != -1) { ///u 104 break; 105 } ///u 106 } //o 107 if (levelrr == -1) { //s 108 levelrr = sikilong; 109 } //s 110 b = siki.substring(levellr + 1, levelrr); 111 sikipb = siki.substring(levelrr, sikilong - 1); 112 if (levelrr == sikilong - 1){ 113 sikipb = ""; 114 } 115 if (siki.charAt(levelrl) == sisoku[2]) { //t 116 en = a * b; 117 } else if (siki.charAt(levelrl) == sisoku[3]) { //t 118 en = a / b; 119 } //t 120 if (levelll == 0){ 121 sikipa = ""; 122 } 123 siki = sikipa + en + sikipb; 124 sikilong = siki.length; 125 } //4 126 //+-の計算 127 var nisokuth = 0; 128 for (var cntf = 0; cntf <= sikilong; cntf++) { 129 for (var cntnumd = 0; cntnumd < 4; cntnumd++) { 130 if (sisoku[cntnumd] == siki.charAt(cntf)) { 131 nisokuth++; 132 } 133 } 134 } 135 for (var cntmainb = 0; cntmainb <= nisokuth; cntmainb++) { //1 136 var middle = -1; 137 for (var cntg = 0; cntg < sikilong; cntg++) { //2 138 for (var cntnume = 0; cntnume < 2; cntnume++) { //3 139 if (sisoku[cntnume] == siki.charAt(cntg)) { //4 140 var middle = cntg; 141 break; 142 } //4 143 if (middle != -1) { //5 144 break; 145 } //5 146 } //3 147 if (middle == -1) { 148 break; 149 } 150 var lrright = -1; 151 var llleft = 0; 152 var llright = middle - 1; 153 var lrleft = middle + 1; 154 for (var cntaa = lrleft; cntaa < sikilong - lrleft + 1; cntaa++) { 155 for (var cntnumaa = 0; cntnumaa < 2; cntnumaa++) { 156 if (sisoku[cntnumaa] == siki.charAt(cntaa)) { 157 lrright = cntaa - 1; 158 break; 159 } 160 } 161 if (lrright == -1) { 162 lrlight = sikilong; 163 } 164 } 165 var a = siki.substring(llleft, llright); 166 var b = siki.substring(lrleft, lrright); 167 if (siki.charAt(middle) == sisoku[0]) { 168 en = a + b; 169 } else if (siki.charAt(middle) == sisoku[1]) { 170 en = a - b; 171 } 172 var sikipb = substring(lrright, sikilong); 173 siki = en + sikipb; 174 } //2 175 if (middle == -1) { 176 alert("答え:" + siki); 177 return; 178 } 179 } //1 180 /*}catch(e){ 181 alert("式が不適合もしくはエラーです。"); 182 return; 183 } 184 finally{ 185 return; 186 }*/ 187} //a

###試したこと
コードを見たらわかるかと思いますが、括弧がちゃんと対応しているか英数字をふって確かめたりしました。
デバッグも粗方行いました。

###補足情報(言語/FW/ツール等のバージョンなど)
特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

matobaa

2017/01/05 14:44

3か所ほど、if文中の比較すべきところで代入しているように見えるところがありますが意図通りでしょうか? ところでhttp://jsbeautifier.org/ に貼り付けて Beautifierボタンを押すときれいに整形してくれますよ。
ko20vonobird

2017/01/05 15:07

まず、整形できるサイトを教えてくださりありがとうございます。ところで、現在確認中ですが、それが条件式の中であれば私のミスです。そうでなければ意図通りのはずです。
kei344

2017/01/05 15:14

「最初の文字は数字に」とありますが、「-1」も数字です。これは無視するということで問題ないですか?
ko20vonobird

2017/01/05 15:23

kei344さん、書くのを忘れていました、今のバージョンは自然数で四則演算をする場合のみ対応するという設定で設計しております。なので、-の場合は今はメモにしてあるtryでエラーとして検出しようと思っております。
guest

回答4

0

参考までに、似た要件のコードを書いたことがあります。

質問文に書かれたコードは全体的に見通しが悪いので、和算/減算/積算/除算をそれぞれ関数化してコードを分けて切り分けすると問題点がはっきりして良いと思います。
細かな最適化は後でも出来ます。

Re: ko20vonobird さん

投稿2017/01/05 22:49

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko20vonobird

2017/01/06 00:34

think49さん、回答ありがとうございます。四則に分けて計算をさせるのが良いことは存じております。一方で、私の個人的な課題としまして一つの関数で全ての計算ができるように目指しております。なので、今回は大変恐縮で、かつコードとしても汚いのは承知の上で、進められたらと思います。
ozwk

2017/01/06 01:23

> 私の個人的な課題としまして一つの関数で全ての計算ができるように目指しております なんでそんなことを?
ko20vonobird

2017/01/06 01:30

ozwkさん、質問ありがとうございます。質問にの題名の横にある通り私は初心者です、故に、スマートなやり方は私にとっては少々知識を更に要求されると思うからです。また、今まで他の言語を勉強してきたときもまずは粗削りなコードを書くことでまずはおおまかな流れをつかもうと試みています。要は、分割するやり方は書くのに複雑ではないかと思慮し、まずは汚くても流れがつかめる方をしようと思ったのです。
koronatail

2017/01/06 01:37

>ko20vonobirdさん 回答ではないので恐縮ですが、今回のバグについては言語の仕様云々というよりアルゴリズムの間違いによるバグに見えます。 勉強のためにあえてこうしているというのであればご自身でデバッグしていったほうがいいと思いますよ。 数分デバッグしただけですが時間をかけて処理を追っていけば十分修正できる内容だと感じました。
ko20vonobird

2017/01/06 01:47

koronatailさん、ありがとうございます、なるほど、直せるレベルのものでしたか。私初心者であるが故ついつい自分では直せないかと思い込んでいました。しかしおかげで修正できるものだとわかりました。あとはできる限り自分でデバッグして修正していこうと思います、ありがとうございます。
guest

0

全体をスクロールする程度に読みましたが、頭に入ってきにくいというのが感想です。
相当な熟練者でもない限り、このコードを一読して指摘・修正するのは難しいのではないでしょうか。
質問者の方は初心者ということですが、そのレベルと逸脱した
上級者にしかわからないコード(上級者向けのコードとは違います)を書いているということになります。
誰でも(数か月後の自分も)読めるコードを書くのが、プログラミングには必要です。

具体的には
●変数の説明をコメントに記述する(説明がいらないような命名が理想です)
例)nisokukw・・・*と/の数
●行う処理の説明をコメントしておく(これも説明がいらないようなfunction名などで処理を分けるのが理想です)

さて、具体的なコードは書きませんが、私なら以下のフローで書くと思います。()は使わないという前提です。

1 フォームの文字列を加算、減算で分解
"5-4/6-8+9/72+5-78"

[ ["+" , "5" ] , ["-" , "4/6"] , ["-" , "8"] , ["+" , "9/72"] , ["+" , "5"] , ["-" , "78"] ]
とする。
2 各配列の第二要素をそれぞれ計算。
3 各配列の第一要素にのっとって、第二要素を集計

ご参考になれば、幸甚です。

投稿2017/01/06 02:31

namimon

総合スコア726

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko20vonobird

2017/01/06 06:31

なるほど、今の状態は雑に組み上げたハウスのような感じなのですね。分かりやすく整えられるように頑張ります。 そのやり方は思いつきませんでした、参考にさせていただきます、ありがとうございます。
guest

0

"javascript expression eval" で google 検索すると 数式の評価を javascript で行うことに関する情報をえられます。

たとえば

ソースコードは https://github.com/silentmatt/expr-eval/blob/master/parser.js

数式の評価の実装は、コンパイラ、インタープリターをつくる際も入門的な知識が必要です。

他にもこんなページがみつかります。

これらのコードを研究してみてから、質問文のコードをみなおすとよいと思います。

投稿2017/01/06 22:27

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

乱暴ですが要件を満たすだけならeval関数で計算できるんじゃないでしょうか。

javascript

1function keisan(){ 2 var ans = eval("10*10*30"); 3 alert(ans); 4}

evalを使うくらいならthink49さんが製作した関数を使うほうがよさそうですが。
コード自体はsubstringの文字の切り出し位置がずれて計算が正しく行えていないように感じましたが、このレベルのバグになると作った本人がデバッグで地道に修正していくのが一番早いじゃないでしょうか。
どうしてもこの方式を大きく変えたくないというのであれば、think49さんのおっしゃるとおり一旦和算/減算/積算/除算それぞれの計算を行う関数に分割してデバッグしたほうがいいような気がします。
問題点が分かってからくっつけてもいいわけですし。
4つの計算関数を作ったうえで、文字列式の書式チェックを行って必要な関数を呼び出す四則演算関数を別に作るとかもありかもしれません。

投稿2017/01/06 01:30

koronatail

総合スコア433

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ko20vonobird

2017/01/06 01:44

koronatailさん、回答ありがとうございます。evalは初めて知ったのですが、あらゆる文字列を整形するような機能を持つということで合っていますでしょうか? 確かに、切り出し位置がずれているところが非常に多く、私のミスで大変申し訳ないです。 もうしばらく待ってみて、回答が来なければ、質問を終了することも検討します(未解決ですが)。 ところで、式の答えでNaNがでることがあるのですが、これの原因として考えられるものは何でしょうか?
koronatail

2017/01/06 02:35

>ko20vonobirdさん eval関数は「与えられた文字列をJavascriptのコードとして評価する」関数です。 たとえば以下のような式を実行すると「ハロー」という内容のアラートが表示されます。  eval("alert('ハロー')"); テキストボックスの値をそのままevalに突っ込んだりすると何が起こるかわからないので利用方法はよく考える必要があります。PHP等のevalに比べると危険性は低いですが、それでも単に四則演算をしたいだけというのであればthink49さんの関数を使ったほうがいいと思います。 答えでNaNが出ているのは、substringの文字列切り出しの位置がずれてしまい「"10" × "10*"」のような計算を行ってしまっているのが原因のようですね。
ko20vonobird

2017/01/06 06:29

>koronatailさん なるほど、万能というわけではないのですね。 そういうことが起きていたのですか、理解しました、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問