4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

java で地域(ロケール)による小数点の扱いの違い(ピリオド . カンマ ,)を確認する

4
Posted at

概要

最近、小数点の扱いが地域により . か , で異なり予期せぬ動作を起こしたと話題になっていました。
参考: https://twitter.com/sekiyadn/status/1689650550235881472

こちらも初めて知った仕様だったので他言語(java)でも再現するのか試してみました。

確認内容

以下プログラムを実行して結果を比較してみる。
実行時にシステムプロパティで言語と地域を指定しました。
(OS をフランス語に変更すると復旧不可能になりそうなので…)

  • 日本
    • -Duser.language=ja -Duser.country=JP
  • フランス
    • -Duser.language=fr -Duser.country=FR
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;

public class DecimalChecker {
	public static void main(String[] args) throws ParseException {
		System.out.println(Float.parseFloat("3.5"));
		try {
			System.out.println(Float.parseFloat("3,5"));
		} catch (Exception e) {
			System.out.println("Float.parseFloat(\"3,5\") " + e);
		}

		System.out.println(DecimalFormat.getInstance().parse("3.5"));
		System.out.println(DecimalFormat.getInstance().parse("3,5"));

		System.out.println(NumberFormat.getInstance().parse("3.5"));
		System.out.println(NumberFormat.getInstance().parse("3,5"));

		System.out.println(new BigDecimal("3.5"));
		System.out.println(new BigDecimal("3,5"));
	}
}

比較結果

Amazon Corretto 11 と 17 で結果は変わらずでした
XXXFormat の parse で差分が出ています。

処理内容 Ja_JP fr_FR
Float.parseFloat("3.5") 3.5 3.5
Float.parseFloat("3,5") NumberFormatException NumberFormatException
DecimalFormat.getInstance().parse("3.5") 3.5 3
DecimalFormat.getInstance().parse("3,5") 35 3.5
NumberFormat.getInstance().parse("3.5") 3.5 3
NumberFormat.getInstance().parse("3,5") 35 3.5
new BigDecimal("3.5") 3.5 3.5
new BigDecimal("3,5") NumberFormatException NumberFormatException
  • Float.parseFloat の例外

    java.lang.NumberFormatException: For input string: "3,5"

  • new BigDecimal("3,5") の例外

    java.lang.NumberFormatException: Character , is neither a decimal digit number, decimal point, nor "e" notation exponential mark.

まとめ

  • 例外が発生するならまだ良いが予期せぬ値にパースしている可能性がある

  • ユーザが入力する、設定ファイル等で指定する場合の扱いには気をつける

  • ロケールが指定出来る機能には気をつける

    • XXXFormat の getInstance はデフォルトのロケールで取得します。
    • ロケールを指定することで実行環境に依らず固定の Format を取得できる
      • DecimalFormat.getInstance(Locale.FRANCE).parse("3,5")
  • java の場合は Float.parseFloatnew BigDeceimal を使うのが無難だと思う

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?