Javaでは浮動小数点型の数値で正確な計算結果を求める場合、BigDecimalクラスを使用する必要があります。floatやdoubleでも計算は出来ますがこれらは浮動小数点型(要は2進数で計算する)の為、小数点以下の数値が正確に表現出来ないため誤差が発生するためです。それではBigDecimalクラスの使用方法をご紹介します。
BigDecimalでの加算処理
Javaソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * <p>[概 要] BigDecimalでの加算処理</p> * <p>[詳 細] </p> * <p>[備 考] </p> * @param numStr1 文字列型数値1 * @param numStr2 文字列型数値2 * @return numStr1とnumStr2の加算結果(パラメータがnullの場合はnullを返します。) */ public static BigDecimal addBigDecimal(String numStr1, String numStr2){ if(numStr1 == null || numStr2 == null){ // パラメータがnullの場合、nullを返します return null; } // BigDecimalの生成 BigDecimal dec1 = new BigDecimal(numStr1); BigDecimal dec2 = new BigDecimal(numStr2); // 加算処理 dec1 = dec1.add(dec2); return dec1; } |
JUnitサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Test public void addBigDecimalTest() { // 準備 String str1 = "123.45"; String str2 = "456.78"; // 期待値 BigDecimal expected = new BigDecimal("580.23"); // 実行 BigDecimal result1 = UtilSample1.addBigDecimal(str1, str2); BigDecimal result2 = UtilSample1.addBigDecimal(str1, null); BigDecimal result3 = UtilSample1.addBigDecimal(null, str2); BigDecimal result4 = UtilSample1.addBigDecimal(null, null); // 検証 assertEquals("加算結果が一致していません。", expected, result1); assertNull("加算結果がNULLではありません。", result2); assertNull("加算結果がNULLではありません。", result3); assertNull("加算結果がNULLではありません。", result4); } |
BigDecimalでの減算処理
Javaソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/** * <p>[概 要] BigDecimalでの減算処理</p> * <p>[詳 細] </p> * <p>[備 考] </p> * @param numStr1 文字列型数値1 * @param numStr2 文字列型数値2 * @param opt 減算値(1:numStr1からnumStr2を減算、2:numStr2からnumStr1を減算) * @return numStr1とnumStr2の加算結果(パラメータがnullの場合はnullを返します。) */ public static BigDecimal subBigDecimal(String numStr1, String numStr2, int opt){ if(numStr1 == null || numStr2 == null || (opt != 1 && opt != 2)){ // パラメータがnullまたはオプションが1,2以外の場合、nullを返します return null; } // BigDecimalの生成 BigDecimal dec1 = new BigDecimal(numStr1); BigDecimal dec2 = new BigDecimal(numStr2); // 減算処理 BigDecimal sub = new BigDecimal("0.00"); if(opt == 1) { sub = dec1.subtract(dec2); } else if(opt == 2) { sub = dec2.subtract(dec1); } return sub; } |
JUnitサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Test public void subBigDecimalTest() { // 準備 String str1 = "123.45"; String str2 = "456.78"; // 期待値 BigDecimal expected1 = new BigDecimal("-333.33"); BigDecimal expected2 = new BigDecimal("333.33"); // 実行 BigDecimal result1 = UtilSample1.subBigDecimal(str1, str2, 1); BigDecimal result2 = UtilSample1.subBigDecimal(str1, str2, 2); BigDecimal result3 = UtilSample1.subBigDecimal(str1, null, 1); BigDecimal result4 = UtilSample1.subBigDecimal(null, str2, 1); BigDecimal result5 = UtilSample1.subBigDecimal(null, null, 3); // 検証 assertEquals("減算結果が一致していません。", expected1, result1); assertEquals("減算結果が一致していません。", expected2, result2); assertNull("減算結果がNULLではありません。", result3); assertNull("減算結果がNULLではありません。", result4); assertNull("減算結果がNULLではありません。", result5); } |
BigDecimalでの乗算処理
Javaソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * <p>[概 要] BigDecimalでの乗算処理</p> * <p>[詳 細] </p> * <p>[備 考] </p> * @param numStr1 文字列型数値1 * @param numStr2 文字列型数値2 * @return numStr1とnumStr2の乗算結果(パラメータがnullの場合はnullを返します。) */ public static BigDecimal multiBigDecimal(String numStr1, String numStr2){ if(numStr1 == null || numStr2 == null){ // パラメータがnullの場合、nullを返します return null; } // BigDecimalの生成 BigDecimal dec1 = new BigDecimal(numStr1); BigDecimal dec2 = new BigDecimal(numStr2); // 乗算処理 dec1 = dec1.multiply(dec2); return dec1; } |
JUnitサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Test public void multiBigDecimalTest() { // 準備 String str1 = "123.45"; String str2 = "456.78"; // 期待値 BigDecimal expected = new BigDecimal("56389.4910"); // 実行 BigDecimal result1 = UtilSample1.multiBigDecimal(str1, str2); BigDecimal result2 = UtilSample1.multiBigDecimal(str1, null); BigDecimal result3 = UtilSample1.multiBigDecimal(null, str2); BigDecimal result4 = UtilSample1.multiBigDecimal(null, null); // 検証 assertEquals("乗算結果が一致していません。", expected, result1); assertNull("乗算結果がNULLではありません。", result2); assertNull("乗算結果がNULLではありません。", result3); assertNull("乗算結果がNULLではありません。", result4); } |
BigDecimalでの除算処理
-
- 除算する場合、BigDecimalクラスのdivideメソッド使用します。第3パラメータへ以下の丸め方法を指定する事が出来ます。
-
丸め方式 説明(Javadocより) ROUND_UP 0 から離れるように丸めるモード。
破棄される 0 以外の小数部に先行する桁を常に増やします。ROUND_DOWN 0 に近づくように丸めるモード。
破棄される小数部に先行する桁を増分しません (つまり切り詰め)。ROUND_CEILING 正の無限大に近づくように丸めるモード。
BigDecimal が正の場合は ROUND_UP のように動作し、負の場合は ROUND_DOWN のように動作します。ROUND_FLOOR 負の無限大に近づくように丸めるモード。
BigDecimal が正の場合は ROUND_DOWN のように動作し、負の場合は ROUND_UP のように動作します。ROUND_HALF_UP 「もっとも近い数字」に丸めるモード。
両隣りの数字が等距離の場合は切り上げます。破棄される小数部が 0.5 以上の場合は ROUND_UP のように動作し、それ以外の場合は ROUND_DOWN のように動作します。ROUND_HALF_DOWN 「もっとも近い数字」に丸めるモード。
両隣りの数字が等距離の場合は切り捨てます。破棄される小数部が 0.5 を超える場合は ROUND_UP のように動作し、それ以外の場合は ROUND_DOWN のように動作します。ROUND_HALF_EVEN 「もっとも近い数字」に丸める丸めモード。
両隣りの数字が等距離の場合は偶数側に丸めます。破棄する小数部の左辺の桁が奇数の場合は ROUND_HALF_UP のように動作し、偶数の場合は ROUND_HALF_DOWN のように動作します。ROUND_UNNECESSARY 要求される演算の結果が正確であり、丸めが必要でないことを表す丸めモード。
この丸めモードが結果が正確でない演算で指定される場合は、ArithmeticException がスローされます。
Javaソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/** * <p>[概 要] BigDecimalでの除算処理</p> * <p>[詳 細] </p> * <p>[備 考] </p> * @param dividend 被除数 * @param divisor 除数 * @param roundType 丸め方式(0:UP, 1:DOWN, 2:CEILING, 3:FLOOR, 4:HALF_UP, 5:HALF_DOWN, 6:HALF_EVEN, 7:UNNECESSARY) * @param minority 少数第何位で処理するかを指定(例:2なら少数第3位の値を丸めます) * @return dividend÷のdivisorの除算結果:商(少数) */ public static BigDecimal divideBigDecimal(String numStr1, String numStr2, Integer roundType, Integer minority) throws ArithmeticException{ if(numStr1 == null || numStr2 == null || roundType == null ||minority == null || roundType.intValue() > 7){ // パラメータがnullの場合、nullを返します return null; } // BigDecimalの生成 BigDecimal dec1 = new BigDecimal(numStr1); BigDecimal dec2 = new BigDecimal(numStr2); // 除算処理 BigDecimal divide = dec1.divide(dec2, minority.intValue(), roundType.intValue()); return divide; } |
JUnitサンプル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
@Test public void divideBigDecimalTest() { // 準備 String str1 = "7"; String str2 = "8"; // 期待値 BigDecimal expected1 = new BigDecimal("0.88"); BigDecimal expected2 = new BigDecimal("0.87"); BigDecimal expected3 = new BigDecimal("0.88"); BigDecimal expected4 = new BigDecimal("0.87"); BigDecimal expected5 = new BigDecimal("0.88"); BigDecimal expected6 = new BigDecimal("0.87"); BigDecimal expected7 = new BigDecimal("0.88"); // 実行 BigDecimal result1 = UtilSample1.divideBigDecimal(str1, str2, 0, 2); BigDecimal result2 = UtilSample1.divideBigDecimal(str1, str2, 1, 2); BigDecimal result3 = UtilSample1.divideBigDecimal(str1, str2, 2, 2); BigDecimal result4 = UtilSample1.divideBigDecimal(str1, str2, 3, 2); BigDecimal result5 = UtilSample1.divideBigDecimal(str1, str2, 4, 2); BigDecimal result6 = UtilSample1.divideBigDecimal(str1, str2, 5, 2); BigDecimal result7 = UtilSample1.divideBigDecimal(str1, str2, 6, 2); // 検証 assertEquals("除算結果が一致していません。", expected1, result1); assertEquals("除算結果が一致していません。", expected2, result2); assertEquals("除算結果が一致していません。", expected3, result3); assertEquals("除算結果が一致していません。", expected4, result4); assertEquals("除算結果が一致していません。", expected5, result5); assertEquals("除算結果が一致していません。", expected6, result6); assertEquals("除算結果が一致していません。", expected7, result7); } @Test(expected = ArithmeticException.class) public void divideBigDecimalTest_RoundUnnecessary() { // 準備 String str1 = "7"; String str2 = "8"; // 実行 UtilSample1.divideBigDecimal(str1, str2, 7, 2); } |