- JAVA
Javaの四捨五入|Math.round・切り捨て・切り上げと桁指定
Javaで小数を整数に丸めるときは、四捨五入が Math.round、切り捨てが Math.floor、切り上げが Math.ceil です。小数第2位などの桁を指定して正確に丸めたいときは、BigDecimal.valueOf(値).setScale(桁数, RoundingMode.HALF_UP) を使います。 ただし、負の数では Math.round(-2.5) が -2 になるなど、学校で習う四捨五入と結果が違う場面があります。
この記事では、Math.round・floor・ceil・rint・(int) キャスト・BigDecimal.setScale を、2.5、-2.5、2.4、-2.6 などの正負の値で比べた一覧表を Java 21.0.10 の実行結果で示します。さらに、小数第n位で丸めるコピペ用メソッド(double 版で 1.005 が 1.0 になる理由と BigDecimal 版)、new BigDecimal(2.675) で誤差が出る様子、RoundingMode 全8種の一覧表、表示だけ丸める String.format と DecimalFormat(既定は HALF_EVEN)の違いまでまとめました。
Javaの四捨五入・切り捨て・切り上げの早見表
| やりたいこと | 書き方 | 2.5 | -2.5 | 戻り値の型 |
|---|---|---|---|---|
| 四捨五入(整数に) | Math.round(x) |
3 | -2 | long(float なら int) |
| 四捨五入(負の数も0から遠ざける) | BigDecimal.valueOf(x).setScale(0, RoundingMode.HALF_UP) |
3 | -3 | BigDecimal |
| 切り捨て(小さい方へ) | Math.floor(x) |
2.0 | -3.0 | double |
| 切り捨て(0の方へ) | (int) x / RoundingMode.DOWN |
2 | -2 | int |
| 切り上げ(大きい方へ) | Math.ceil(x) |
3.0 | -2.0 | double |
| 切り上げ(0から遠ざける) | RoundingMode.UP |
3 | -3 | BigDecimal |
| 偶数丸め(最近接偶数への丸め) | Math.rint(x) / RoundingMode.HALF_EVEN |
2.0 | -2.0 | double / BigDecimal |
| 小数第2位までに四捨五入 | BigDecimal.valueOf(x).setScale(2, RoundingMode.HALF_UP) |
2.50 | -2.50 | BigDecimal |
| 表示だけ小数第2位まで | String.format("%.2f", x) |
2.50 | -2.50 | String |
| 整数の割り算を切り上げ | Math.ceilDiv(a, b)(Java 18以降) |
― | ― | int / long |
ポイント
Math.roundは、おおむね「+0.5 して小さい方へ切り捨て」と同じ動きです。負の数の .5 は 0 に近い方(-2.5 → -2)になります。Math.floorとMath.ceilは double を返すので、int にするにはキャストが必要です。- 桁を指定して正確に丸めるなら BigDecimal。生成は
BigDecimal.valueOf(double)か文字列から行います。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Javaの四捨五入|Math.round・切り捨て・切り上げと桁指定」
実行環境
$ java -version
openjdk version "21.0.10" 2026-01-20
OpenJDK Runtime Environment (build 21.0.10+7-Ubuntu-124.04)
OpenJDK 64-Bit Server VM (build 21.0.10+7-Ubuntu-124.04, mixed mode, sharing)
# 単一ファイル実行(日本語の出力用に stdout.encoding を指定)
$ java -Dstdout.encoding=UTF-8 Compare.java
Java 25 の API ドキュメント(java.lang.Math)で確認した範囲では、round・floor・ceil・rint の仕様は Java 21 と同じです(公式ドキュメントで確認。Java 25 では動かしていません)。
Math.round・floor・ceil・rint・キャスト・BigDecimal の比較一覧
6つの方法を、正の数と負の数で一度に比べます。
import java.math.BigDecimal;
import java.math.RoundingMode;
// 小数点以下を整数に丸める方法を、正の数・負の数で比較する
public class Compare {
public static void main(String[] args) {
double[] values = {2.5, 2.4, 2.6, 1.5, 0.5, -0.5, -1.5, -2.4, -2.5, -2.6};
System.out.println("値 round floor ceil rint (int) HALF_UP HALF_EVEN");
for (double v : values) {
BigDecimal bd = BigDecimal.valueOf(v);
System.out.printf("%5.1f %5d %5.1f %5.1f %5.1f %5d %7s %9s%n",
v,
Math.round(v), // long を返す
Math.floor(v), // double を返す
Math.ceil(v),
Math.rint(v),
(int) v, // 0 の方向へ切り捨て
bd.setScale(0, RoundingMode.HALF_UP).toPlainString(),
bd.setScale(0, RoundingMode.HALF_EVEN).toPlainString());
}
System.out.println("Math.round(2.5f) の型: " + ((Object) Math.round(2.5f)).getClass().getSimpleName()
+ " / Math.round(2.5) の型: " + ((Object) Math.round(2.5)).getClass().getSimpleName());
System.out.println("Math.floor(2.7) = " + Math.floor(2.7) + "(double)");
System.out.println("Math.round(NaN) = " + Math.round(Double.NaN)
+ " / Math.round(1e20) = " + Math.round(1e20)
+ " / (int) 1e20 = " + (int) 1e20);
System.out.println("Math.round(0.49999999999999994) = " + Math.round(0.49999999999999994));
}
}
実行結果(Java 21.0.10):
値 round floor ceil rint (int) HALF_UP HALF_EVEN
2.5 3 2.0 3.0 2.0 2 3 2
2.4 2 2.0 3.0 2.0 2 2 2
2.6 3 2.0 3.0 3.0 2 3 3
1.5 2 1.0 2.0 2.0 1 2 2
0.5 1 0.0 1.0 0.0 0 1 0
-0.5 0 -1.0 -0.0 -0.0 0 -1 0
-1.5 -1 -2.0 -1.0 -2.0 -1 -2 -2
-2.4 -2 -3.0 -2.0 -2.0 -2 -2 -2
-2.5 -2 -3.0 -2.0 -2.0 -2 -3 -2
-2.6 -3 -3.0 -2.0 -3.0 -2 -3 -3
Math.round(2.5f) の型: Integer / Math.round(2.5) の型: Long
Math.floor(2.7) = 2.0(double)
Math.round(NaN) = 0 / Math.round(1e20) = 9223372036854775807 / (int) 1e20 = 2147483647
Math.round(0.49999999999999994) = 0
結果を表に整理
| 値 | Math.round | Math.floor | Math.ceil | Math.rint | (int) | HALF_UP | HALF_EVEN |
|---|---|---|---|---|---|---|---|
| 2.5 | 3 | 2.0 | 3.0 | 2.0 | 2 | 3 | 2 |
| 2.4 | 2 | 2.0 | 3.0 | 2.0 | 2 | 2 | 2 |
| 2.6 | 3 | 2.0 | 3.0 | 3.0 | 2 | 3 | 3 |
| 1.5 | 2 | 1.0 | 2.0 | 2.0 | 1 | 2 | 2 |
| 0.5 | 1 | 0.0 | 1.0 | 0.0 | 0 | 1 | 0 |
| -0.5 | 0 | -1.0 | -0.0 | -0.0 | 0 | -1 | 0 |
| -1.5 | -1 | -2.0 | -1.0 | -2.0 | -1 | -2 | -2 |
| -2.4 | -2 | -3.0 | -2.0 | -2.0 | -2 | -2 | -2 |
| -2.5 | -2 | -3.0 | -2.0 | -2.0 | -2 | -3 | -2 |
| -2.6 | -3 | -3.0 | -2.0 | -3.0 | -2 | -3 | -3 |
表から読み取れること
Math.roundは .5 のとき常に大きい方(正の無限大の方向)へ丸めます。 そのため -2.5 は -2、-0.5 は 0 です。公式ドキュメントにも「ties rounding to positive infinity(ちょうど中間なら正の無限大の方へ)」と書かれています。- 「-2.5 を -3 にしたい」(0 から遠ざける四捨五入)なら
RoundingMode.HALF_UPを使います。 Math.floorは小さい方、(int)キャストは 0 の方へ切り捨てます。正の数では同じですが、-2.4 は floor で -3.0、キャストで -2 と分かれます。Math.ceil(-0.5)は-0.0になりました。-0.0は0.0と==では等しいものの、表示に「-」が付きます。表示に使うときは int にキャストするか、+ 0.0で0.0にそろえます。Math.rintとHALF_EVENは「偶数丸め」:ちょうど .5 のときは偶数の方へ丸めます(2.5 → 2、1.5 → 2、0.5 → 0)。
戻り値の型と範囲外の値
| メソッド | 引数 double のとき | 引数 float のとき | 注意 |
|---|---|---|---|
Math.round |
long | int | int x = Math.round(2.5); はコンパイルエラー(long から int への変換)。(int) Math.round(v) か Math.toIntExact(Math.round(v)) |
Math.floor / ceil / rint |
double | (double に変換) | int が欲しいときは (int) Math.floor(v) |
(int) キャスト |
int | int | 範囲外は Integer.MAX_VALUE などに張り付く |
Math.round(NaN) は 0、Math.round(1e20) は Long.MAX_VALUE、(int) 1e20 は Integer.MAX_VALUE になりました。例外は出ないので、入力の範囲が広い場合は事前にチェックするか、Math.toIntExact で範囲外を例外にします。
Math.round(0.49999999999999994) が 0 になる点も確認しました。同じ値で Math.floor(0.49999999999999994 + 0.5) を計算すると、足し算の時点で誤差が出て 1.0 になります。「+0.5 して floor」を自分で書くより、Math.round を使う方が正確です。
int n = Math.round(2.5); と書くと、次のコンパイルエラーになりました(Java 21.0.10)。
Ce.java:1: error: incompatible types: possible lossy conversion from long to int
public class Ce { public static void main(String[] a) { int n = Math.round(2.5); } }
^
1 error
小数第n位で丸めるコピペ用メソッド
「小数第3位を四捨五入して、小数第2位までにする」ような桁指定の丸めは、よく次のように書かれます。
// よく見かける double 版
static double roundDouble(double value, int scale) {
double p = Math.pow(10, scale);
return Math.round(value * p) / p;
}
この書き方と BigDecimal 版を、いくつかの値で比べました。
import java.math.BigDecimal;
import java.math.RoundingMode;
// 小数第 n 位で丸める:double 版と BigDecimal 版
public class Digits {
// double 版(よく見かける書き方)
static double roundDouble(double value, int scale) {
double p = Math.pow(10, scale);
return Math.round(value * p) / p;
}
// BigDecimal 版(おすすめ)
static BigDecimal round(double value, int scale, RoundingMode mode) {
return BigDecimal.valueOf(value).setScale(scale, mode);
}
public static void main(String[] args) {
double[] values = {1.005, 2.675, 1.255, 0.125, 8.345, -1.005, 123.456};
System.out.println("値 x*100 の中身 double版 BigDecimal版(HALF_UP)");
for (double v : values) {
System.out.printf("%-8s %-24s %-9s %s%n",
v, String.valueOf(v * 100), roundDouble(v, 2), round(v, 2, RoundingMode.HALF_UP));
}
System.out.println("切り捨て(DOWN) 1.239 → " + round(1.239, 2, RoundingMode.DOWN)
+ " / -1.239 → " + round(-1.239, 2, RoundingMode.DOWN));
System.out.println("切り捨て(FLOOR) 1.239 → " + round(1.239, 2, RoundingMode.FLOOR)
+ " / -1.239 → " + round(-1.239, 2, RoundingMode.FLOOR));
System.out.println("切り上げ(UP) 1.231 → " + round(1.231, 2, RoundingMode.UP)
+ " / -1.231 → " + round(-1.231, 2, RoundingMode.UP));
System.out.println("切り上げ(CEILING) 1.231 → " + round(1.231, 2, RoundingMode.CEILING)
+ " / -1.231 → " + round(-1.231, 2, RoundingMode.CEILING));
System.out.println("百の位に丸める 1250 → " + BigDecimal.valueOf(1250).setScale(-2, RoundingMode.HALF_UP).toPlainString()
+ " / 1249 → " + BigDecimal.valueOf(1249).setScale(-2, RoundingMode.HALF_UP).toPlainString());
System.out.println("double に戻す: " + round(2.675, 2, RoundingMode.HALF_UP).doubleValue());
System.out.println("整数(1.50)の表示: " + round(1.5, 2, RoundingMode.HALF_UP)
+ " / stripTrailingZeros: " + round(1.5, 2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString());
}
}
実行結果(Java 21.0.10):
値 x*100 の中身 double版 BigDecimal版(HALF_UP)
1.005 100.49999999999999 1.0 1.01
2.675 267.5 2.68 2.68
1.255 125.49999999999999 1.25 1.26
0.125 12.5 0.13 0.13
8.345 834.5000000000001 8.35 8.35
-1.005 -100.49999999999999 -1.0 -1.01
123.456 12345.6 123.46 123.46
切り捨て(DOWN) 1.239 → 1.23 / -1.239 → -1.23
切り捨て(FLOOR) 1.239 → 1.23 / -1.239 → -1.24
切り上げ(UP) 1.231 → 1.24 / -1.231 → -1.24
切り上げ(CEILING) 1.231 → 1.24 / -1.231 → -1.23
百の位に丸める 1250 → 1300 / 1249 → 1200
double に戻す: 2.68
整数(1.50)の表示: 1.50 / stripTrailingZeros: 1.5
double 版の落とし穴
1.005 を小数第2位に四捨五入すると、期待は 1.01 ですが、double 版は 1.0 になりました。原因は 1.005 * 100 が 100.49999999999999 になることです。
double は2進数で値を持つため、1.005 はぴったり表せず、実際には 1.00499999999999989... という少しだけ小さい値として記録されています。100 を掛けた時点でその差が表に出て、Math.round が 100 に丸めます。1.255 も同じ理由で 1.25 になりました。
BigDecimal 版は、BigDecimal.valueOf(1.005) が Double.toString(1.005)="1.005" を元に作られるため、見た目どおりの 1.005 として丸められ、1.01 になります。
| 方法 | 1.005 → | 1.255 → | -1.005 → | 戻り値 |
|---|---|---|---|---|
Math.round(x * 100) / 100.0 |
1.0 | 1.25 | -1.0 | double |
BigDecimal.valueOf(x).setScale(2, HALF_UP) |
1.01 | 1.26 | -1.01 | BigDecimal |
そのまま使えるメソッド(用途に合わせて RoundingMode を変えます):
import java.math.BigDecimal;
import java.math.RoundingMode;
public final class Rounding {
private Rounding() {}
/** 小数第 scale 位までに四捨五入(-2.5 → -3 のように 0 から遠ざける) */
public static BigDecimal halfUp(double value, int scale) {
return BigDecimal.valueOf(value).setScale(scale, RoundingMode.HALF_UP);
}
/** 小数第 scale 位までに切り捨て(0 の方へ:-1.239 → -1.23) */
public static BigDecimal down(double value, int scale) {
return BigDecimal.valueOf(value).setScale(scale, RoundingMode.DOWN);
}
/** 小数第 scale 位までに切り上げ(0 から遠ざける:-1.231 → -1.24) */
public static BigDecimal up(double value, int scale) {
return BigDecimal.valueOf(value).setScale(scale, RoundingMode.UP);
}
/** 文字列で受け取った値を丸める(入力がもともと文字列なら、こちらがより正確) */
public static BigDecimal halfUp(String value, int scale) {
return new BigDecimal(value).setScale(scale, RoundingMode.HALF_UP);
}
/** 結果を double で欲しいとき */
public static double halfUpAsDouble(double value, int scale) {
return halfUp(value, scale).doubleValue();
}
}
切り捨て・切り上げは「0の方」か「小さい方」かを決める
負の数を扱うときは、「切り捨て」が 0 の方へ(DOWN)なのか、小さい方へ(FLOOR)なのかを先に決めます。
| やりたいこと | RoundingMode | 1.239 → | -1.239 → |
|---|---|---|---|
| 切り捨て(0 の方へ、絶対値を小さく) | DOWN |
1.23 | -1.23 |
切り捨て(小さい方へ、Math.floor と同じ向き) |
FLOOR |
1.23 | -1.24 |
| やりたいこと | RoundingMode | 1.231 → | -1.231 → |
|---|---|---|---|
| 切り上げ(0 から遠ざける、絶対値を大きく) | UP |
1.24 | -1.24 |
切り上げ(大きい方へ、Math.ceil と同じ向き) |
CEILING |
1.24 | -1.23 |
整数の位で丸める・末尾の0を消す
setScaleに負の数を渡すと、整数の位で丸められます。setScale(-2, HALF_UP)は十の位を四捨五入して百の位までにする指定で、1250 → 1300、1249 → 1200 になりました(toPlainString()で1.3E+3のような指数表記を避けています)。setScale(2)の結果は常に小数2桁(1.5 →1.50)です。末尾の0を消したいときはstripTrailingZeros().toPlainString()を使います。
new BigDecimal(2.675) と BigDecimal.valueOf(2.675) の違い
BigDecimal を使っても、new BigDecimal(double) で作ると、double の誤差をそのまま引き継ぎます。
import java.math.BigDecimal;
import java.math.RoundingMode;
// new BigDecimal(double) と BigDecimal.valueOf(double) の違い
public class Ctor {
public static void main(String[] args) {
double d = 2.675;
BigDecimal a = new BigDecimal(d);
BigDecimal b = BigDecimal.valueOf(d);
BigDecimal c = new BigDecimal("2.675");
System.out.println("new BigDecimal(2.675) = " + a);
System.out.println("BigDecimal.valueOf(2.675) = " + b);
System.out.println("new BigDecimal(\"2.675\") = " + c);
System.out.println("小数第2位に HALF_UP:");
System.out.println(" new BigDecimal(2.675) → " + a.setScale(2, RoundingMode.HALF_UP));
System.out.println(" BigDecimal.valueOf(2.675) → " + b.setScale(2, RoundingMode.HALF_UP));
System.out.println(" new BigDecimal(\"2.675\") → " + c.setScale(2, RoundingMode.HALF_UP));
System.out.println("Double.toString(2.675) = " + Double.toString(d));
System.out.println("new BigDecimal(0.1) = " + new BigDecimal(0.1));
System.out.println("BigDecimal.valueOf(0.1 + 0.2) = " + BigDecimal.valueOf(0.1 + 0.2));
}
}
実行結果(Java 21.0.10):
new BigDecimal(2.675) = 2.67499999999999982236431605997495353221893310546875
BigDecimal.valueOf(2.675) = 2.675
new BigDecimal("2.675") = 2.675
小数第2位に HALF_UP:
new BigDecimal(2.675) → 2.67
BigDecimal.valueOf(2.675) → 2.68
new BigDecimal("2.675") → 2.68
Double.toString(2.675) = 2.675
new BigDecimal(0.1) = 0.1000000000000000055511151231257827021181583404541015625
BigDecimal.valueOf(0.1 + 0.2) = 0.30000000000000004
new BigDecimal(2.675) は、double が実際に持っている値 2.67499999999999982... を1桁も欠かさず BigDecimal にするため、四捨五入すると 2.67 になります。BigDecimal.valueOf(2.675) は Double.toString の結果("2.675")から作るので、2.68 になります。
| 作り方 | 中身 | HALF_UP で小数第2位 | 使う場面 |
|---|---|---|---|
new BigDecimal(2.675) |
2.674999999...(double の正確な値) | 2.67 | double の正確な値を調べたいとき |
BigDecimal.valueOf(2.675) |
2.675 | 2.68 | double から変換するとき |
new BigDecimal("2.675") |
2.675 | 2.68 | 入力が文字列のとき(最も確実) |
ただし、BigDecimal.valueOf(0.1 + 0.2) は 0.30000000000000004 でした。valueOf が直せるのは「double に変換したときの表示上の誤差」までで、double どうしで計算した結果の誤差は直せません。 計算そのものを正確に行いたい場合は、最初から BigDecimal で計算します。BigDecimal の四則演算・割り算の丸め・compareTo での比較は、別記事「Java BigDecimalの使い方|金額計算の丸めと比較の注意点」で詳しく扱っています。
RoundingMode 全8種の一覧表
java.math.RoundingMode には8つのモードがあります。公式ドキュメントの例と同じ値で、小数第1位を丸めて整数にした結果です。
import java.math.BigDecimal;
import java.math.RoundingMode;
// RoundingMode 全8種で、小数第1位を丸めて整数にする
public class Modes {
public static void main(String[] args) {
String[] inputs = {"5.5", "2.5", "1.6", "1.1", "1.0", "-1.0", "-1.1", "-1.6", "-2.5", "-5.5"};
System.out.printf("%-12s", "モード");
for (String s : inputs) System.out.printf("%6s", s);
System.out.println();
for (RoundingMode mode : RoundingMode.values()) {
System.out.printf("%-12s", mode);
for (String s : inputs) {
String r;
try {
r = new BigDecimal(s).setScale(0, mode).toPlainString();
} catch (ArithmeticException e) {
r = "例外";
}
System.out.printf("%6s", r);
}
System.out.println();
}
try {
new BigDecimal("1.1").setScale(0, RoundingMode.UNNECESSARY);
} catch (ArithmeticException e) {
System.out.println("UNNECESSARY の例外: " + e);
}
}
}
実行結果(Java 21.0.10):
モード 5.5 2.5 1.6 1.1 1.0 -1.0 -1.1 -1.6 -2.5 -5.5
UP 6 3 2 2 1 -1 -2 -2 -3 -6
DOWN 5 2 1 1 1 -1 -1 -1 -2 -5
CEILING 6 3 2 2 1 -1 -1 -1 -2 -5
FLOOR 5 2 1 1 1 -1 -2 -2 -3 -6
HALF_UP 6 3 2 1 1 -1 -1 -2 -3 -6
HALF_DOWN 5 2 2 1 1 -1 -1 -2 -2 -5
HALF_EVEN 6 2 2 1 1 -1 -1 -2 -2 -6
UNNECESSARY 例外 例外 例外 例外 1 -1 例外 例外 例外 例外
UNNECESSARY の例外: java.lang.ArithmeticException: Rounding necessary
| モード | 日本語での呼び方 | 動き | 2.5 | -2.5 | 1.6 | -1.6 | 近い Math のメソッド |
|---|---|---|---|---|---|---|---|
UP |
切り上げ(0から遠ざける) | 端数があれば絶対値を大きく | 3 | -3 | 2 | -2 | なし |
DOWN |
切り捨て(0の方へ) | 端数を捨てる | 2 | -2 | 1 | -1 | (int) キャスト |
CEILING |
切り上げ(正の方へ) | 大きい方へ | 3 | -2 | 2 | -1 | Math.ceil |
FLOOR |
切り捨て(負の方へ) | 小さい方へ | 2 | -3 | 1 | -2 | Math.floor |
HALF_UP |
四捨五入 | .5 は 0 から遠ざける | 3 | -3 | 2 | -2 | (正の数では Math.round) |
HALF_DOWN |
五捨六入 | .5 は 0 の方へ | 2 | -2 | 2 | -2 | なし |
HALF_EVEN |
偶数丸め(最近接偶数への丸め) | .5 は偶数の方へ | 2 | -2 | 2 | -2 | Math.rint |
UNNECESSARY |
丸めなし | 端数があれば例外 | 例外 | 例外 | 例外 | 例外 | なし |
使い分けの目安
- 学校で習う四捨五入は
HALF_UP。負の数も「絶対値で四捨五入して符号を付ける」動きです。 HALF_EVENは、たくさんの値を丸めて合計したときに偏りが出にくい丸め方です。.5 を常に切り上げると合計が少しずつ大きくなるのに対し、偶数側に寄せることで上下が打ち消し合います。UNNECESSARYは「丸めが起きないはず」の確認用です。端数があるとArithmeticException: Rounding necessaryが出るので、想定外の端数に気づけます。Math.roundと完全に同じ動きのモードはありません(正の数は HALF_UP、負の数は HALF_DOWN と同じ結果)。負の数も扱う処理では、Math.roundと HALF_UP のどちらに合わせるかを決めて統一すると分かりやすくなります。
表示だけ丸める:String.format と DecimalFormat の違い
計算結果はそのままにして、画面やログに出すときだけ小数第2位までにしたい場合は、String.format(または formatted)や DecimalFormat を使います。この2つは丸め方が違います。
import java.math.RoundingMode;
import java.text.DecimalFormat;
// 表示だけ丸める:String.format と DecimalFormat の丸め方の違い
public class Display {
public static void main(String[] args) {
double[] values = {0.5, 1.5, 2.5, -2.5, 2.675, 1.005, 0.125};
DecimalFormat df0 = new DecimalFormat("0");
DecimalFormat df2 = new DecimalFormat("0.00");
DecimalFormat df2up = new DecimalFormat("0.00");
df2up.setRoundingMode(RoundingMode.HALF_UP);
System.out.println("DecimalFormat の既定の丸め: " + df0.getRoundingMode());
System.out.println("値 %.0f DF(0) %.2f DF(0.00) DF(0.00)+HALF_UP");
for (double v : values) {
System.out.printf("%-6s %-4s %-5s %-6s %-8s %s%n",
v, String.format("%.0f", v), df0.format(v),
String.format("%.2f", v), df2.format(v), df2up.format(v));
}
System.out.println("formatted: " + "%.1f".formatted(0.25) + " / %,.2f: " + String.format("%,.2f", 1234567.891));
}
}
実行結果(Java 21.0.10):
DecimalFormat の既定の丸め: HALF_EVEN
値 %.0f DF(0) %.2f DF(0.00) DF(0.00)+HALF_UP
0.5 1 0 0.50 0.50 0.50
1.5 2 2 1.50 1.50 1.50
2.5 3 2 2.50 2.50 2.50
-2.5 -3 -2 -2.50 -2.50 -2.50
2.675 3 3 2.68 2.67 2.67
1.005 1 1 1.01 1.00 1.00
0.125 0 0 0.13 0.12 0.13
formatted: 0.3 / %,.2f: 1,234,567.89
わかったこと
DecimalFormatの既定の丸めはHALF_EVEN(偶数丸め)です。new DecimalFormat("0").format(2.5)は 2、0.5 は 0 になりました。String.format("%.0f", ...)は HALF_UP の動きで、2.5 → 3、-2.5 → -3 でした。setRoundingMode(RoundingMode.HALF_UP)を指定した DecimalFormat でも、2.675 は 2.67、1.005 は 1.00 になりました。DecimalFormat は double が実際に持っている値(2.67499...)を元に丸めるためです。一方String.format("%.2f")は 2.68・1.01 で、こちらはDouble.toStringと同じ「見た目の10進数」を元に丸めた結果になっています。- 0.125 は2進数でぴったり表せる値なので、ちょうど中間として扱われ、HALF_EVEN では 0.12、HALF_UP では 0.13 になりました。
| 方法 | 既定の丸め | 2.5 → 整数 | 2.675 → 小数2桁 | 向いている用途 |
|---|---|---|---|---|
String.format("%.2f", x) / "%.2f".formatted(x) |
HALF_UP | 3 | 2.68 | ログ・簡単な表示 |
new DecimalFormat("0.00") |
HALF_EVEN | 2 | 2.67 | 3桁区切り・パターン指定の表示 |
DecimalFormat + setRoundingMode(HALF_UP) |
HALF_UP | 3 | 2.67 | 表示の丸め方をそろえたいとき |
BigDecimal.valueOf(x).setScale(2, HALF_UP).toPlainString() |
指定どおり | 3 | 2.68 | 表示と計算の結果をそろえたいとき |
表示の丸めと計算の丸めを一致させたいときは、先に BigDecimal で丸めてから表示すると、表示方法による違いが出ません。
整数どうしの割り算の丸め
int どうしの割り算は、小数部分を 0 の方へ切り捨てます。切り上げや「小さい方への切り捨て」は Math.ceilDiv(Java 18以降)と Math.floorDiv(Java 8以降)が使えます。
// 整数どうしの割り算の丸め
public class IntDiv {
public static void main(String[] args) {
int[][] pairs = {{7, 2}, {-7, 2}, {10, 3}, {-10, 3}};
System.out.println("a / b a/b floorDiv ceilDiv 四捨五入");
for (int[] p : pairs) {
int a = p[0], b = p[1];
System.out.printf("%3d/%d %4d %8d %7d %8d%n",
a, b, a / b, Math.floorDiv(a, b), Math.ceilDiv(a, b), Math.round((double) a / b));
}
// 件数からページ数を求める(切り上げ)
int total = 101, perPage = 20;
System.out.println("ページ数: " + Math.ceilDiv(total, perPage) + " / " + ((total + perPage - 1) / perPage));
}
}
実行結果(Java 21.0.10):
a / b a/b floorDiv ceilDiv 四捨五入
7/2 3 3 4 4
-7/2 -3 -4 -3 -3
10/3 3 3 4 3
-10/3 -3 -4 -3 -3
ページ数: 6 / 6
-7 / 2 は -3(0 の方へ)、Math.floorDiv(-7, 2) は -4(小さい方へ)です。101件を20件ずつ表示するページ数のような「切り上げ」は、Math.ceilDiv(101, 20) で 6 になります(Java 17 以前なら (a + b - 1) / b。正の数のときに使える書き方です)。
よくある間違いと直し方
| よくある書き方 | 起きること | 直し方 |
|---|---|---|
int n = Math.round(2.5); |
コンパイルエラー(long を int に代入) | (int) Math.round(v) または float 版 Math.round(2.5f) |
Math.round(-2.5) を四捨五入として使う |
-2 になる | 負の数も扱うなら setScale(0, RoundingMode.HALF_UP) |
Math.round(x * 100) / 100 |
整数どうしの割り算で小数が消える(1.2345 → 1) | / 100.0 にする。より正確には BigDecimal |
Math.round(x * 100) / 100.0 |
1.2345 → 1.23 は正しいが、1.005 → 1.0 | BigDecimal.valueOf(x).setScale(2, HALF_UP) |
new BigDecimal(2.675) |
2.67 に丸まる | BigDecimal.valueOf(2.675) か new BigDecimal("2.675") |
(int) Math.floor(-2.4) と (int) -2.4 を同じと思う |
-3 と -2 で違う | 「0の方」か「小さい方」かを決める |
new DecimalFormat("0").format(2.5) |
2(HALF_EVEN) | setRoundingMode(RoundingMode.HALF_UP) |
setScale(2)(モード指定なし)で端数がある |
new BigDecimal("1.234").setScale(2) で ArithmeticException: Rounding necessary("1.5" なら 1.50 で正常) |
setScale(2, RoundingMode.HALF_UP) のようにモードを必ず渡す |
よくある質問
Q. Math.round(-2.5) が -3 ではなく -2 になるのはなぜですか?
A. Math.round は「ちょうど中間(.5)のときは正の無限大の方へ丸める」と決められているためです(公式ドキュメントの「ties rounding to positive infinity」)。-2.5 の場合、正の方向にある -2 が選ばれます。-2.5 を -3 にしたい場合は BigDecimal.valueOf(-2.5).setScale(0, RoundingMode.HALF_UP) を使います。
Q. 小数第2位までに四捨五入するいちばん簡単で正確な書き方は?
A. BigDecimal.valueOf(x).setScale(2, RoundingMode.HALF_UP) です。double が必要なら最後に .doubleValue() を付けます。Math.round(x * 100) / 100.0 は短く書けますが、1.005 が 1.0 になるような誤差が出ることがあります。
Q. 切り捨ては Math.floor と (int) キャストのどちらを使えばよいですか?
A. 正の数だけなら同じ結果です。負の数で「-2.4 → -3」としたいなら Math.floor(FLOOR)、「-2.4 → -2」としたいなら (int) キャスト(DOWN)です。小数の桁を指定する場合は、BigDecimal の RoundingMode.FLOOR / DOWN を使います。
Q. HALF_UP と HALF_EVEN はどちらを使うべきですか? A. 画面に表示する値や、仕様書に「四捨五入」と書かれている値は HALF_UP が一般的です。たくさんの値を丸めてから合計する集計処理で、丸めによる偏りを減らしたい場合は HALF_EVEN が向いています。どちらを使うかを仕様として決め、コードのあちこちで混ざらないようにメソッドにまとめておくと安心です。
まとめ
- 四捨五入は
Math.round、切り捨てはMath.floor、切り上げはMath.ceil。round は long(float なら int)、floor/ceil は double を返す Math.round(-2.5)は -2。負の数も 0 から遠ざけて四捨五入するならRoundingMode.HALF_UP- 切り捨て・切り上げは「0の方(DOWN/UP)」か「小さい方・大きい方(FLOOR/CEILING)」かを決める。
(int)キャストは 0 の方へ - 小数第n位の丸めは
BigDecimal.valueOf(x).setScale(n, RoundingMode.HALF_UP)。double 版では 1.005 が 1.0 になった new BigDecimal(2.675)は 2.67 に丸まる。double から作るならvalueOf、文字列ならnew BigDecimal("2.675")- RoundingMode は8種。HALF_EVEN は偶数丸め、UNNECESSARY は端数があると例外
DecimalFormatの既定は HALF_EVEN(2.5 → 2)。String.formatは HALF_UP(2.5 → 3)
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Javaの四捨五入|Math.round・切り捨て・切り上げと桁指定」
株式会社RJCでは、数値の丸めのような基本を実行結果で確かめながら仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。