【Java入門】BigDecimalの大小をcompareToで比較する方法

こんにちは!侍エンジニアインストラクターの本多です。

皆さんは、金融や科学計算などの、厳密な計算が求められるシーンで使用されるBigDecimalをご存知ですか?この記事では、

BigDecimalとは?
compareToメソッドとは?

という基本的な疑問から、

  • BigDecimalの大小をcompareToで比較する方法
  • equalsメソッドで比較する場合の注意点

などの応用的な内容に関しても解説していきます。

なお、Javaの記事については、こちらにまとめています。

目次

BigDecimalとは

BigDecimalは小数点以下の値に誤差が出ないように正確に計算するために使います。BigDecimalを使わない場合にどのような誤差が出るのか、次のサンプルコードで確認してみましょう。

class Sample {
    public static void main (String[] args){
        System.out.println(1.00 - 0.1 * 9);  
    }
}

[実行結果]

0.09999999999999998

この実行結果から、「1 – 0.9」が「0.1」にならないことが確認できます。このサンプルコードをBigDecimalを使って書き換えると、次のようになります。

import java.math.BigDecimal;

class Sample1 {
    public static void main (String[] args){
    	BigDecimal hoge = new BigDecimal("1.0");
    	BigDecimal huga = new BigDecimal("9");
    	BigDecimal piyo = new BigDecimal("0.1");
    	BigDecimal result = hoge.subtract(huga.multiply(piyo));	

    	System.out.println(result);
    }
}

[実行結果]

0.1

実行結果から、誤差がなく正しく計算ができていることが確認できます。サンプルコードからわかるように、BigDecimalは基本データ型ではなくクラスです。そのため、単純に「+」や「-」の記号を使って四則演算ができません。

BigDecimalを使った四則演算についてまとめると、次のようになります。

  • 足し算 add()
  • 引き算 subtract()
  • 掛け算 multiply()
  • 割り算 divide()

間違えないように気を付けましょう。

BigDecimalの大小をcompareToで比較する

ここではBigDecimalの比較について解説します。BigDecimalは不等号での比較ができません。そのため、BigDecimalの比較はcompareToメソッドを使います。

compareToメソッドとは

ここではcompareToの仕様について解説します。

import java.math.BigDecimal;
 
class Sample2 {
    public static void main (String[] args){
        BigDecimal three = new BigDecimal(3);
        BigDecimal five = new BigDecimal(5);
 
        int result1 = three.compareTo(five);
        System.out.println("result1 = " + result1);
        int result2 = three.compareTo(three);
        System.out.println("result2 = " + result2);
        int result3 = five.compareTo(three);
        System.out.println("result3 = " + result3);
    }
}

[実行結果]

result1 = -1
result2 = 0
result3 = 1

このように、値1.compareTo(値2)とすると、以下のようになります。

  • 値1 < 値2 ならば、-1を返す
  • 値1 = 値2 ならば、 0を返す
  • 値1 > 値2 ならば、 1を返す

compareToメソッドの使い方

compareToを使ってBigDecimal同士を比較する場合、戻り値を0と比較して大小関係を判定することができます。次のプログラムで確認してみましょう。

import java.math.BigDecimal;

class Sample3 {
    public static void main (String[] args){
        BigDecimal three = new BigDecimal(3);
        BigDecimal four = new BigDecimal(4);

        if (three.compareTo(four) < 0) {
            System.out.println("result1 : < ");
        }
        if (three.compareTo(three) == 0) {
            System.out.println("result2 : = ");
        }
        if (four.compareTo(three) > 0) {
            System.out.println("result3 : > ");
        }
    }
}

[実行結果]

result1 : < 
result2 : = 
result3 : >

実行結果から、正しく比較の判定ができていることがわかります。小さい場合のみしか比較しなくて良い場合は、次のようにすることもできます。

// 抜粋
if (three.compareTo(four) == -1) {
System.out.println("result1 : < ");
}

この例では小さい場合のみしか比較できません。全ての比較演算子(<、==、>、>=、!=、<=)を使うためには、compareToの戻り値をゼロと比較します。

equalsメソッドで比較する場合の注意点

BigDecimalをゼロで比較する場合も注意が必要です。まず、以下のコードを見てください。文字列オブジェクトの比較で頻繁に使われるequalsメソッドを使っています。

import java.math.BigDecimal;

class Sample4 {
    public static void main (String[] args){
        BigDecimal zero1 = new BigDecimal("0");
        BigDecimal zero2 = new BigDecimal("0.0");

        if (zero1.equals(BigDecimal.ZERO)) {
            System.out.println("zero1 = 0 ");
        }
        if (zero2.equals(BigDecimal.ZERO)) {
            System.out.println("zero2 = 0 ");
        }
    }
}

[実行結果]

zero1 = 0 

あれ、zero2はゼロと判定されていない。

そうです、BigDecimalはスケール(要は小数点以下、と思ってください)を厳密に区別しています。0と0.0は異なる数字と認識されるのです。ちなみに、上記コードのequalsをcompareToに変えてみてください。

zero1とzero2の2つとも、0と認識されます。

// 抜粋
if (zero1.compareTo(BigDecimal.ZERO) == 0) {
    System.out.println("zero1 = 0 ");
}
if (zero2.compareTo(BigDecimal.ZERO) == 0) {
    System.out.println("zero2 = 0 ");
}

[実行結果]

zero1 = 0 
zero2 = 0

compareToの使い方の総まとめ記事はこちら

compareToメソッドで大小を比較するいろいろな方法を次の記事にまとめているので、ぜひ確認してください!

BigDecimalの使い方の総まとめ記事はこちら

BigDecimalのさまざまな使い方についてはこちらで詳しく解説しているので、ぜひ確認してください!

まとめ

今回はBigDecimalについて解説しました。BigDecimalは正確な値を使うために必要なので間違えずに使用してくださいね。ぜひ、本記事をきっかけとして理解を深めてください

この記事を書いた人

関西在住のITエンジニアです。普通の会社に勤務しながら、侍エンジニアのインストラクター、ライターとして活動しています。

目次