- PR -

BigDecimalの計算について

1
投稿者投稿内容
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2005-11-25 13:29
みーちくと申します。
宜しくお願いいたします。

BigDecimal型を使用して、計算を行っております。
計算の仕様は下記の通りです。
・小数第3位を四捨五入
・1000.00%以上の場合は、999.99%を表示する
メソッドを作成し、小数第3位を四捨五入はできたのですが、
表示がうまくいきません。
下記のコードを実行した場合、6666.70%と返されます。
DecimalFormatを使用しない場合の計算、66.667です。
私としては、66.70が返されるのかなと思ったのですが、違ってました。
DecimalFormatを使用しないで、setScale()をすればよいのでしょうか?
宜しくお願い致します。

コード:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;

public class TEST03 {

    public static void main(String[] args) {
        String str1 = "100";
        String str2 = "150";
        System.out.println(getROUND(str1, str2));
    }

    /**
	 * 小数点第3位を四捨五入します。
	 * @param str1 分子
	 * @param str2 分母
	 * @return 値
	 */
	public static String getROUND(String str1, String str2) {
		String ret;
		try {
			BigDecimal bd1 = new BigDecimal(str1);
			BigDecimal bd2 = new BigDecimal(str2);
			ret = getROUND(bd1, bd2);
		} catch (Exception e) {
			ret = "";
		}
		return ret;
	}

	/**
	 * 小数点第3位を四捨五入します。
	 * @param bd1 分子
	 * @param bd2 分母
	 * @return 値
	 */
	public static String getROUND(BigDecimal bd1, BigDecimal bd2) {
		BigDecimal bd;
		DecimalFormat nf = new DecimalFormat(".00%");
		final int SCALE = 3;
		try {
		    if(bd1 == null || bd2 == null || bd2.compareTo(new BigDecimal("0")) == 0) {
				throw new Exception();
			} else {
			    bd1 = bd1.multiply(new BigDecimal("100"));
				bd = bd1.divide(bd2, SCALE, BigDecimal.ROUND_HALF_UP);
			}
		} catch (Exception e) {
			bd = new BigDecimal(new BigInteger("0"), SCALE);
		}
		System.out.println(bd.toString());
		return nf.format(bd);
	}
}

Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2005-11-25 13:58
引用:

みーちくさんの書き込み (2005-11-25 13:29) より:

下記のコードを実行した場合、6666.70%と返されます。
DecimalFormatを使用しない場合の計算、66.667です。
私としては、66.70が返されるのかなと思ったのですが、違ってました。


APIには、下記の通りにあります。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/text/DecimalFormat.html
% 接頭辞または接尾辞 あり 100 倍してパーセントを表す

というわけで、「".00%"」の場合、これは演算結果が「0.667」のときに
「66.70%」と表示するためのパターンです。
みーちくさんの場合、自分で100を掛けてらっしゃいますから「6667.00%」になるのです。
さぷり
会議室デビュー日: 2005/11/18
投稿数: 18
投稿日時: 2005-11-25 13:59
こんにちわ。

DecimalFormatでフォーマットパターンに「%」を指定した場合は、
DecimalFormat側で自動的に100倍してパーセント表示します。
詳細については、DecimalFormatのJavaDocに書いてありますよ。

なので、ロジックで100倍する必要がなく、
bd1 = bd1.multiply(new BigDecimal("100"));
部分をコメントアウトすれば、みーちくさんの意図通りの結果になると思います。
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2005-11-25 13:59
DecimalFormatが、フォーマット文字列中の"%"を検知して
自動的に百分率表記(=BigDecimalが所有する値を100倍に
する)に変換してくれているのではないでしょうか。

みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2005-11-25 14:23
Edossonさん、さぷりさん、シュンさん

返信ありがとうございました。
DecimalFormatで指定していたのですね。
APIの確認をしておりませんでした。

皆様、ありがとうございました。
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2005-11-25 14:31
解決したあとでなんですが。

「66.70%」と表示される数値は、
100分率の場合は、「有効桁数4桁」と見なされるべきものです。
3桁だったら「66.7%」と表示します。
[追記]
いや、「100分率小数部有効桁数2桁で66.70」でいいのか。
でも、実際は「小数部2桁目」で四捨五入してるし。ううむ。
[/追記]
引用:

・小数第3位を四捨五入
・1000.00%以上の場合は、999.99%を表示する


この仕様にしてからが、有効桁数2桁と4桁の仕様が混じってますので、
どちらか一方に統一されることをお勧めします。
[追記]
「3桁」を「2桁」に修正
[/追記]

先に書いておくべきでしたね。
[追記]
そもそもBigDecimalのscaleに3を指定すると、「小数第3位を四捨五入」になりませんぞ。
つっこんだところがつっこみどころ満載で、
なんか、いろいろ恥ずかしいなあ・・・。orz
[/追記]

[ メッセージ編集済み 編集者: Edosson 編集日時 2005-11-25 15:26 ]
1

スキルアップ/キャリアアップ(JOB@IT)