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

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

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

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

3回答

6009閲覧

Java電卓の小数の計算がズレます

newtorino

総合スコア47

Java

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

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2015/11/18 09:20

編集2015/11/19 02:45

電卓をつくっています。
少数の計算が微妙にズレて正しく結果が表示されません。

例えば、
5.3 + 2.3 = 5.9999999...
7.3 + 2.5 = 9.80000000...
このように、微妙にズレて結果がだされてしまい困っています。

希に、
6.3 + 2.3 = 8.5
など、ちゃんと結果を出してくれることもあります・・・。

プラスするところのコードはこんな感じです

Java

1 if (kigou1.equals("+")) {//プラスが押された場合ここに入る 2 suuji1 = mae + Double.valueOf(textView.getText().toString()); //前回入力した数値に、今テキストビューにある数字を足す。結果をsuuji1に入れる。 3 bbb = new BigDecimal(suuji1); //suuji1をBigDecimalに変換 4 textView.setText(String.valueOf(bbb)); //結果をテキストビューに表示 5 mae = suuji1; //結果を「前回入力した数値」にいれる

よろしくお願いします。

-----------------------追記-------------------------------
(返信コメントのコピペですが失礼します)

ご回答、ありがとうございます。
BigDecimalは使い方がDoubleにくらべ難しいのでDoubleからBigDecimalに変換する。
という形で使ったのですが、すべてBigDecimalにしないとよろしくないみたいですね。

BigDecimalを使って新しく書き直してみたのですが、
比較の仕方がイマイチわからないのでつまっています。よろしければそちらも教えていただけないでしょうか。

Java

1 2BigDecimal mae = BigDecimal.ZERO 3if (mae == 0){ //ビッグデシマルのmaeが0の時、ここに入る 4} 5

上記のようなことをやりたいのですが、うまくいきません。
他にも
if(mae.equals(0))
もやってみましたがうまくいきません。
BigDecimalの比較方法に、compareToというのもあるようですが
型同士で比較するモノみたいですので、ここで使うのは違う気がする・・・

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

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

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

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

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

guest

回答3

0

10 / 3 * 3 は bigdecimal を使っても 10 にはならないと思います (多分)
10/3 は無限桁の小数だからです。
分数として計算をすれば、 10 になります。
ruby には Ratinal クラスとして、分数を扱えるクラスがあります。
java にあるかは知りません。
私は Scala で 分数で計算できるクラスを作ったことがあります。
https://github.com/katoy/scala_rational
https://github.com/katoy/node-rational (←はnode.js 版)

投稿2015/11/18 12:20

編集2015/11/18 12:58
katoy

総合スコア22324

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

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

KiyoshiMotoki

2015/11/18 12:46 編集

katoy様、横から失礼します。 > 10 / 3 * 3 は bigdecimal を使っても 10 にはならないと思います 実際に実行してみたところ、10 / 3 の部分でエラーになりましたorz import java.math.BigDecimal; public class Main {   /**    * @param args    */   public static void main(String[] args) {     BigDecimal bd1 = BigDecimal.valueOf(10);     BigDecimal bd2 = bd1.divide(BigDecimal.valueOf(3)); // ここでエラー     BigDecimal bd3 = bd2.multiply(BigDecimal.valueOf(3));     System.out.println(bd1);     System.out.println(bd2);     System.out.println(bd3);   } } 実行結果 Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(BigDecimal.java:1603) at Main.main(Main.java:10) BigDecimalは、丸めモードを指定しないと、結果が無限小数となるような割り算はできないようです。 https://docs.oracle.com/javase/jp/6/api/java/math/BigDecimal.html#divide(java.math.BigDecimal) 紹介いただいたScalaプログラム、素晴らしいですね! ちょうど、Scalaを勉強中ですので、参考にさせていただきます。
katoy

2015/11/18 13:04

excel のセル値の計算を、分数や循環小数表記でできるようにして、 計算誤差なしの計算モードをもつ表計算アプリ を提案を会社にしたことがあります。(却下されましたが)
KiyoshiMotoki

2015/11/18 13:08

それは熱いですね! 却下されてしまったのは残念です。。
newtorino

2015/11/19 02:49

ご返信ありがとうございます。 BigDecimalを使うだけでなく、丸めるという動作も必要なんですね。 ひとまず、正常な動きが作れたら試してみたいと思います! BigDecimalについてなのですが、使っていて比較の仕方もわからなくなってしまいました。 質問内容は、記事を編集して追記しましたのでよろしければそちらの回答もお願いしたいです。 よろしくお願い致します。
newtorino

2015/11/19 04:58

丸める動作も正常にできました! 気付かずスルーするとこでした。ありがとうございます!
guest

0

浮動小数点形式では10進数の小数を正確に表現できません。BigDecimalを使って計算してみてください。

投稿2015/11/18 09:22

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

newtorino

2015/11/19 02:42

ご回答、ありがとうございます。 BigDecimalは使い方がDoubleにくらべ難しいのでDoubleからBigDecimalに変換する。 という形で使ったのですが、すべてBigDecimalにしないとよろしくないみたいですね。 BigDecimalを使って新しく書き直してみたのですが、 比較の仕方がイマイチわからないのでつまっています。よろしければそちらも教えていただけないでしょうか。 -------------------------------------------------------- BigDecimal mae = BigDecimal.ZERO if (mae == 0){ //ビッグデシマルのmaeが0の時、ここに入る } -------------------------------------------------------- 上記のようなことをやりたいのですが、うまくいきません。 他にも if(mae.equals(0)) もやってみましたがうまくいきません。 BigDecimalの比較方法に、compareToというのもあるようですが 型同士で比較するモノみたいですので、ここで使うのは違う気がする・・・ お返事いただけたら幸いです。
swordone

2015/11/19 03:04 編集

数値を、オブジェクトを要求する場所に入れた場合、オートボクシングによりIntegerなどに変換されます。 BigDecimalのequalsは同じ値・スケールを持つBigDecimalが引数に渡った場合のみtrueを返すので、Integerなどが相手では比較できません。 0と比較したいのならintValue()でintを引き出して比較するという方法が考えられますが、長すぎる場合は下位32ビットが返ってくる仕様なので、2^32以上の2の累乗の場合は上手く行かないでしょう。 他にはBigDecimal.valueOfで数値をBigDecimalに変換してequals比較するくらいでしょうか。つまりご提示の例なら if(mae.equals(BigDecimal.valueOf(0)){ }
newtorino

2015/11/19 05:00

解説付きでありがとうございます! ふつうにValueOfでやればよかったですね・・・ 慣れないクラスでうっかりしていたようです。 無事解決できました!ありがとうございます!
guest

0

ベストアンサー

floatやdoubleのような浮動小数点形式は2進数の組み合わせで数値ができています。
なので、小数によっては無限小数になることもあります。
その値を組み合わせると、誤差が生じるのです。

BigDecimalは、整数と10の-n乗で成り立っていて、整数で計算するので誤差が生じないという仕組みです。
floatやdoubleに比べれば処理性能は遅いですが、精度を求めるのであればBigDecimalを使うしかないのです。


追記の回答
試したコード

Java

1public class Aa { 2 3 public static void main(String[] args) { 4 BigDecimal mae = new BigDecimal(1.0); 5 mae.setScale(4, BigDecimal.ROUND_HALF_UP); 6 7 if (BigDecimal.ONE.compareTo(mae) == 0) { 8 System.out.println("one"); 9 } else { 10 System.out.println("not"); 11 } 12 } 13}

投稿2015/11/18 10:34

編集2015/11/19 03:11
anonymouskawa

総合スコア856

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

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

退会済みユーザー

退会済みユーザー

2015/11/18 10:36

フォローありがとうございます。電卓アプリなので、処理速度より正確性の方が重要でしょう。
anonymouskawa

2015/11/18 10:46

はい、処理性能が劣るといっても電卓で計算するには全く遜色のないものですし、BigDecimalの使用が良いですね。 suuji1とmaeはdouble型と思うので、この部分をBigDecimalで計算するようにすれば、問題なく小数点の計算ができると思います。
newtorino

2015/11/19 02:51

ご返信、ありがとうございます。 仕組みまで教えて頂き恐縮です。Doubleからの途中変換もあまりよろしくなかったみたいですね。
anonymouskawa

2015/11/19 03:08

追記の答え if (BigDecimal.ZERO.compareTo(mae) == 0 ) { } これで比較はできます。
newtorino

2015/11/19 04:59

compareToでもできるんですね。 ZEROと比較できるとは参考になります。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問