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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

JavaScript

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

Q&A

解決済

3回答

2663閲覧

BigDecimalについて

maru_o

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

JavaScript

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

0グッド

0クリップ

投稿2016/10/27 02:46

精度の高い計算をJavaで行うにはBigDecimalを使用するのが適当と聞き
計算式をformulaに代入し計算処理するプログラムを記述したのですが、1.1*3の結果が3.3000000000000003となり丸め誤差が修正されませんでした。
計算式内の個々の数値と演算子を格納する変数を用意して計算させようとも思ったのですが、複雑になりそうなので止めました。
以下のプログラムを大幅に変更することなく丸め誤差が修正できるよう修正したいのですが、良い方法はございませんでしょうか。

java

1//計算式を格納する 2String formula=""; 3 4try{ 5 ScriptEngineManager factory=new ScriptEngineManager(); 6 ScriptEngine engine=factory.getEngineByName("JavaScript"); 7 BigDecimal result=new BigDecimal( (engine.eval(formula)).toString() ).stripTrailingZeros(); 8 jTextField1.setText(result.toPlainString()); 9}catch(ScriptException ex){ 10 throw new RuntimeException(ex); 11}

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

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

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

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

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

guest

回答3

0

JavaScriptとして実行させていますので、engine.eval(formula)の時点ですでに誤差を含んだ数値となってしまっています(もっと言えば、1.1をJavaScriptで表現した時点で、もはや正確でなくなります)。それをBigDecimalに入れても手遅れです。

JavaScriptとして処理するという手抜きではなく、自前で数式を処理する必要があります。

投稿2016/10/27 03:00

maisumakun

総合スコア145183

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

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

maru_o

2016/10/27 03:05

回答ありがとうございます。 自前で処理ということは、質問文に書いた様に一つ一つ変数を用意して演算子に合わせて数式を処理しなければいけないのでしょうか
maisumakun

2016/10/27 03:59

Stringの数式を構文解析する、という方法もあります(これまた自力で実装しようとすると大変ですが)。
guest

0

BigDecimalに数値として渡すから誤差が生じるのであって、"1.1"という文字列を渡せば正確に計算出来ます。

投稿2016/10/27 07:39

swordone

総合スコア20651

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

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

0

ベストアンサー

Stringの数式を構文解析する、という方法もあります(これまた自力で実装しようとすると大変ですが)。

参考となるコードが
http://stackoverflow.com/questions/3422673/evaluating-a-math-expression-given-in-string-form
にありましたので BigDecimal で書き直してみました。
BigDecimal なので sqrt 等の関数が使えないのでコメントアウトしています。

assertEquals("1.3",Expression.eval("13/10").toString()); assertEquals("1.30",Expression.eval("0.13*10").toString()); assertEquals("1.23",Expression.eval("0.13+1.10").toString()); assertEquals("0.03",Expression.eval("0.13-0.10").toString()); assertEquals("0.03",Expression.eval("-0.10+0.13").toString()); assertEquals("0.03",Expression.eval("+0.13-0.10").toString()); assertEquals("0.03",Expression.eval("+0.13-(0.05+0.05)").toString());

等の動作確認済み。

public static BigDecimal eval(final String str) { return new Object() { int pos = -1, ch; void nextChar() { ch = (++pos < str.length()) ? str.charAt(pos) : -1; } boolean eat(int charToEat) { while (ch == ' ') nextChar(); if (ch == charToEat) { nextChar(); return true; } return false; } BigDecimal parse() { nextChar(); BigDecimal x = parseExpression(); if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch); return x; } // Grammar: // expression = term | expression `+` term | expression `-` term // term = factor | term `*` factor | term `/` factor // factor = `+` factor | `-` factor | `(` expression `)` // | number | functionName factor | factor `^` factor BigDecimal parseExpression() { BigDecimal x = parseTerm(); for (;;) { if (eat('+')) x = x.add(parseTerm()); // addition else if (eat('-')) x = x.subtract(parseTerm()); // subtraction else return x; } } BigDecimal parseTerm() { BigDecimal x = parseFactor(); for (;;) { if (eat('*')) x = x.multiply(parseFactor()); // multiplication else if (eat('/')) x = x.divide(parseFactor()); // division else return x; } } BigDecimal parseFactor() { if (eat('+')) return parseFactor(); // unary plus if (eat('-')) return parseFactor().negate(); // unary minus BigDecimal x; int startPos = this.pos; if (eat('(')) { // parentheses x = parseExpression(); eat(')'); } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers while ((ch >= '0' && ch <= '9') || ch == '.') nextChar(); x = new BigDecimal(str.substring(startPos, this.pos)); } else if (ch >= 'a' && ch <= 'z') { // functions while (ch >= 'a' && ch <= 'z') nextChar(); String func = str.substring(startPos, this.pos); x = parseFactor(); /* if (func.equals("sqrt")) x = Math.sqrt(x); else if (func.equals("sin")) x = Math.sin(Math.toRadians(x)); else if (func.equals("cos")) x = Math.cos(Math.toRadians(x)); else if (func.equals("tan")) x = Math.tan(Math.toRadians(x)); else */ throw new RuntimeException("Unknown function: " + func); } else { throw new RuntimeException("Unexpected: " + (char)ch); } // if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation return x; } }.parse(); }

投稿2016/10/27 04:36

KazuhiroKato

総合スコア46

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

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

maru_o

2016/10/27 14:54

回答ありがとうございます、お返事遅くなり失礼しました。 参考URLとコードを載せていただきありがとうございます。 しかも分かりやすくコーディングまでしていただきありがとうございます、動作を理解できるよう努めたいと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問