LoginSignup
0
0

More than 1 year has passed since last update.

ロケールによって小数点がピリオドかコンマかが変わるので数値⇔文字列変換に注意しよう

Posted at

ロケールによって数値表現が変わるので注意しようってお話です
特にユーザー端末で実行されるアプリでは、様々なロケールでの動作を考慮する必要があります

日本語や英語では小数点に「.」(ピリオド)を使用するため、これ以外の表現が使われることを意識していない人も多いのではないでしょうか?イタリア、ドイツ、フランス、ロシア語などでは「,」(コンマ)が使われるため、変換時に「.」(ピリオド)が使われることを前提にしていると不具合になってしまう場合があります。

ということで、以下を実行してみましょう。

fun main() {
    Locale.setDefault(Locale.JAPAN)
    println("%.1f".format(1.1))
    println(1.1.toString())
    println("1.1".toDoubleOrNull())
    println("1,1".toDoubleOrNull())
    println(DecimalFormat().parse("1,1").toDouble())

    println()

    Locale.setDefault(Locale.FRANCE)
    println("%.1f".format(1.1))
    println(1.1.toString())
    println("1.1".toDoubleOrNull())
    println("1,1".toDoubleOrNull())
    println(DecimalFormat().parse("1,1").toDouble())
}

結果

1.1
1.1
1.1
null
11.0

1,1
1.1
1.1
null
1.1

String.formatDesimalFormat.parseを使った場合はロケール設定が反映されるため挙動が変わります。
一方Double.toString()Double.parseDoubleはロケール設定に影響されず、「.」(ピリオド)が小数点として使われていますね。

表示するために文字列に変換したり、ユーザー入力の値をパースを行う場合はString.formatDesimalFormat.parseを使うのが良いでしょう。
一方、URLなど外部APIアクセスに使用するための文字列や、内部処理のための、文字列⇔数値変換ではDouble.toString()Double.parseDoubleを使用する、String.formatを使う場合はロケールを明示的に指定する必要があります。

ロケールが小数点に影響するとは意識しておらず、この問題になかなか気づけませんでした。
さすがに全言語環境での確認はできませんが、こういう問題もあると言うことを覚えておきましょう。

0
0
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
0
0