【TECH BLOG #64】スマートフォンの言語設定によって計算結果が変わってしまうお話

はじめに
こんにちは。
グリーエンターテインメント株式会社のMです。
みなさんが普段利用しているスマートフォンでは設定で表示する言語を変えることができるのはご存知でしょうか。
スマートフォンに搭載されているAndroidやiOSなどのOSにはテキストをどの言語で表示するかを設定する機能があり、普段スマートフォンを利用する際には無意識に日本語や英語など利用しやすい言語に設定しているのではないかと思います。
今回は、このOSの言語設定によって、Unityで使用されているC#の標準関数の使い方により計算結果が変わってしまうという事例についてご紹介します。
マスタデータの配信
ライブサービス型と呼ばれる、継続的にアップデートを行うタイプのタイトルにおいては、ゲームの設定内容をマスタデータという形で配信し、それをダウンロードすることでゲームの内容を更新しています。
このマスタデータをゲーム内で読み込む際にプログラムで文字列から数値に変換して処理を行うというのは、よく見られる処理の流れなのですが、この文字列から数値に変換する処理において、小数点を含む数値を扱う処理がOSの言語設定によって処理結果が変わってしまうことがありました。
小数点の表記ゆれ
なぜ言語設定によって処理結果が変わってしまったか調査したところ、地域によって小数点の表記が異なるためということが判明しました。
日本では小数点といえば『.』ピリオドですが、地域によっては小数点に『,』カンマを使用しているのはご存知でしょうか。
小数点にピリオドを使用している主な地域
●日本
●中国
●韓国
●イギリス
●アメリカ
●オーストラリア
小数点にカンマを使用している主な地域
●フランス
●ドイツ
●イタリア
●スペイン
●ポルトガル
文字列で小数を含む数値の表記、例えば「123.45」とした場合、日本語を含む小数点にピリオドを使っている言語に設定した状態で、プログラムで数値に変換した場合は期待する数値に「123.45」として変換してくれます。
しかし、小数点にカンマを使用している言語で同じ「123.45」を変換したときに小数点が正しく認識されずに「12345」と意図せず大きな数値として変換されてしまうケースがありました。
想定しない大きなパラメータで計算処理を行うことになってしまうため、当然意図した結果になるはずもありません。
このような背景で、OSの言語設定によって計算結果が変わるという事象が発生しました。
原因
本事象の原因は以下のC#の標準関数の使い方にありました。
> public static float Parse (string s);
こちらを使用すると上記のような結果となります。
対応方法としては、
以下の第二引数に「System.Globalization.CultureInfo.InvariantCulture」を設定します。
> public static float Parse (string s, IFormatProvider? provider);
※他にもオーバーロード関数がありますので、ご確認ください。
「CultureInfo.InvariantCulture」は”カルチャに依存しない (インバリアントな) オブジェクト”です。これを指定することにより小数点が『.』ピリオドとして扱った結果となります。
例)
string magnificationString = “1.25”;
float magnificationA = float.Parse(magnificationString);
// 言語設定がフランスなどの一部の国では小数点にカンマを使用するため、ピリオドは無視されて magnificationA の値が「125」となる
float magnificationB = float.Parse(magnificationString,
System.Globalization.CultureInfo.InvariantCulture);
// 言語設定がフランスでも magnificationB の値は「1.25」となる
まとめ
今回はOSの言語設定という一見アプリの動作には影響しないと思われる箇所が、プログラミング言語の標準関数という思わぬところの挙動を変えてしまい、問題を引き起こすこともあるという事例を紹介させていただきました。
海外で展開していないアプリであれば“日本語のみで配信されているアプリだから大丈夫”とお考えかもしれませんが、OSの言語設定はユーザー自身で変更可能なため影響が出ないとは言い切れません。
基盤レベルで対応しているアプリも多いかもしれませんが、
今一度、float.Perseの引数を確認してみてはいかがでしょうか?
また、マスタデータを設計する際に、あらかじめ小数を含む値に1000倍などして千分率にした整数値を入力すると決めておけば回避することもできるので、小数点の文字列を使用しないことも本現象に対しては有効な手段かと思います。
最後まで読んでいただきありがとうございました。
本件に関するお問い合わせ先
グリーエンターテインメント株式会社 広報担当
東京都港区六本木6-11-1 六本木ヒルズゲートタワー
E-mail:info-ent@ml.gree.net