Javaの負の数の切り捨て・四捨五入にはご注意!

切り捨てや四捨五入は基本的に正の数でやることが多いです。

で、今回業務で負の数の切り捨て・四捨五入を調べていて、Javaではやり方が2通りあり、しかもそれぞれで値が変わってしまうという問題にぶち当たりました。

以下に、切り捨ておよび四捨五入の書き方を示します。(値は一律5.5とします。)

切り捨て

Mathクラスを使用する場合
Math.floor(5.5);
BigDecimalクラスを使用する場合
new BigDecimal(5.5).setScale(0, BigDecimal.ROUND_DOWN).doubleValue();

四捨五入

Mathクラスを使用する場合
Math.round(5.5);
BigDecimalクラスを使用する場合
new BigDecimal(5.5).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();

比較表

各値を代入した場合の結果を表にまとめます。

基準値 切り捨て(Math) 切り捨て(BigDecimal) 四捨五入(Math) 四捨五入(BigDecimal)
5.0 5.0 5.0 5.0 5.0
5.4 5.0 5.0 5.0 5.0
5.5 5.0 5.0 6.0 6.0
5.9 5.0 5.0 6.0 6.0
-5.0 -5.0 -5.0 -5.0 -5.0
-5.4 -6.0 -5.0 -5.0 -5.0
-5.5 -6.0 -5.0 -5.0 -6.0
-5.9 -6.0 -5.0 -6.0 -6.0

値のおかしい箇所を太文字にしました。
どれもMathクラスのメソッドを使用した場合です。

よって、切り捨て・四捨五入はBigDecimalを使用しましょう!

サンプルソース

import java.math.BigDecimal;

public class CalculateMain {
	
	public static void main(String[] args) {
		System.out.println("【正の数】");
		new CalculateMain(5.0);
		new CalculateMain(5.4);
		new CalculateMain(5.5);
		new CalculateMain(5.9);
		System.out.println("");
		System.out.println("【負の数】");
		new CalculateMain(-5.0);
		new CalculateMain(-5.4);
		new CalculateMain(-5.5);
		new CalculateMain(-5.9);
	}
	
	public CalculateMain(double num) {
		System.out.println("-----------------------");
		System.out.println(" Base            : " + num);
		System.out.println("-----------------------");
		System.out.println(" Math.floor      : " + floorOfMath(num));
		System.out.println(" BigDecimal.floor: " + floorOfBigDecimal(num));
		System.out.println(" Math.round      : " + roundOfMath(num));
		System.out.println(" BigDecimal.round: " + roundOfBigDecimal(num));
		System.out.println("");
	}
	
	/**
	 * 小数第1位を切り捨てる。(Mathクラスを使用)
	 */
	public double floorOfMath(double num) {
		return Math.floor(num);
	}

	/**
	 * 小数第1位を切り捨てる。(BigDecimalクラスを使用)
	 */
	public double floorOfBigDecimal(double num) {
		return new BigDecimal(num).setScale(0, BigDecimal.ROUND_DOWN).doubleValue();
	}

	/**
	 * 小数第1位を四捨五入。(Mathクラスを使用)
	 */
	public double roundOfMath(double num) {
		return Math.round(num);
	}

	/**
	 * 小数第1位を四捨五入。(BigDecimalクラスを使用)
	 */
	public double roundOfBigDecimal(double num) {
		return new BigDecimal(num).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

}