例のあれです。
「――おいおい、ゼロ除算なんて起きる場所なんてないのに」
ちょっとはまったので備忘として。
誰かの一助となればこれ幸いです。
ArithmeticExceptionとは
いわゆるゼロ除算(ゼロで割る計算)などを行うと、throwされる例外です。
ゼロ除算時にこの例外が発生する理由としては1/0が定義されていないからだそうです。
1の中に0は一つも存在しないともいえるし、0が無限に存在するとも考えられるとのことでちょっと哲学的な感じですね。
BigDecimalでゼロ除算以外でArithmeticExceptionが起こるケース
今回起こったケースとしては、BigDecimalのdivide(除算)する際に、結果が循環小数になったときに発生しました。( 例:11÷3=3.666666.....)
原因としてはdivideの第2引数で丸め方を指定していなかったことです。この処理の個所ではdivideで丸め方を指定せずに、setScaleで切り捨て、切り上げを行ってしました。
なので、divideを利用する場合は、循環小数になったときに例外を起こさないためにに丸め方を指定してやったほうがいいです。
丸め指定での注意点
結構blogなどで丸め指定を見るとBigDecimal.ROUND_DOWNなどを使用するようなソースがあります。
しかし、java9から@Deprecated(非推奨)になっているので使用の際には一考が必要です。
丸め方指定の場合には、RoundingMode.HALF_UP等を使用することが望ましいようです。
以下に、簡単に一覧を引用しておきます。
CEILING
正の無限大に近づくように丸めるモードです。
DOWN
0に近づくように丸めるモードです。
FLOOR
負の無限大に近づくように丸めるモードです。
HALF_DOWN
「もっとも近い数字」に丸める丸めモードです(両隣りの数字が等距離の場合は切り捨てます)。
HALF_EVEN
「もっとも近い数字」に丸める丸めモードです(ただし、両隣りの数字が等距離の場合は偶数側に丸めます)。
HALF_UP
「もっとも近い数字」に丸める丸めモードです(ただし、両隣りの数字が等距離の場合は切り上げます)。
UNNECESSARY
要求される演算の結果が正確であり、丸めが必要でないことを表す丸めモードです。
UP
0から離れるように丸めるモードです。
【Java】BigDecimalをちゃんと使う~2018~より引用