電卓プログラムで欠かせないのが数字の文字列としての表示です。
表示するためには、各国のくせに応じた表示というのが不可欠で、例えば日本であれば、小数点は「.」ですが、欧州やアラビア諸国では「,」が使われるようです。
数字区切りも、本来日本は4桁のはずが3桁が普及していますが、区切りの桁や、区切り文字も小数点と同様に国によって違っていたりします。
ということで、国に応じた数字表記というのが必要で、Objective-Cの場合は理解しましたが、Swiftでのフォーマットに関する情報が希薄です。
ということで、整理しながら以下に書いていきたいと思います。
(1)数字の入力
電卓の場合、数字の入力は10キーで行いますので、0から9の文字と小数点から構成される文字列となります。これはあくまでも内部処理なので小数点は何でもいいのですが、おそらく標準では「.」だと思われるので、「.」と仮定しておきます。
(2)文字列の数字表記変換
数字表記への変換はNumberFormatterというクラスがあるようです。
NumberFormatterリファレンス:
https://developer.apple.com/documentation/foundation/numberformatter
ただし、このクラスの入力はNSNumberとなるようで、入力された文字列をNSNumberに変換してから入力してあげなくてはなりません。
まずはDoubleに変換します。
ちなみに上の記述で「formatter」はNumberFormatterのインスタンスのことで、利用する前に様々なプロパティを設定してフォーマットを決めていく必要があります。
ここでは暫定的に以下のものとしました。
これらについては追ってつめていきたいと思います。Localeの設定をしているので、上の,と3は不要な気もします。
実行結果の一例です。0が10個表示されるのはどうにかしたいところです。元が文字列の数字ですので、小数点以下の数字の個数がわかればどうにかなりそうです。
そこで、formatterの小数点以下の数値の数を以下のように設定してみました。
ちなみに、小数点以下の長さを-1してますけど、val.countは1からの数になりますが、範囲型は0からの数になるようで、val.countから1を引いてあげる必要があるようです。
この結果はこんな感じで、思惑どおりです。
表示するためには、各国のくせに応じた表示というのが不可欠で、例えば日本であれば、小数点は「.」ですが、欧州やアラビア諸国では「,」が使われるようです。
数字区切りも、本来日本は4桁のはずが3桁が普及していますが、区切りの桁や、区切り文字も小数点と同様に国によって違っていたりします。
ということで、国に応じた数字表記というのが必要で、Objective-Cの場合は理解しましたが、Swiftでのフォーマットに関する情報が希薄です。
ということで、整理しながら以下に書いていきたいと思います。
(1)数字の入力
電卓の場合、数字の入力は10キーで行いますので、0から9の文字と小数点から構成される文字列となります。これはあくまでも内部処理なので小数点は何でもいいのですが、おそらく標準では「.」だと思われるので、「.」と仮定しておきます。
(2)文字列の数字表記変換
数字表記への変換はNumberFormatterというクラスがあるようです。
NumberFormatterリファレンス:
https://developer.apple.com/documentation/foundation/numberformatter
ただし、このクラスの入力はNSNumberとなるようで、入力された文字列をNSNumberに変換してから入力してあげなくてはなりません。
まずはDoubleに変換します。
let doubleValue = Double(val)
Double()は、Doubleに変換できない場合はnilになるオプショナルバリューを返しますが、これ以前に数値となるよう文字列を確認しているため、オプショナルバインディングの記述は不要となっています。
次に、DoubleをNSNumberに変換します。
let nsNumberValue = NSNumber(value: doubleValue!)
ちなみに最後の!は、オプショナルバリューを強制アンラップするということらしいですが、おそらくNSNumber()はオプショナルバユーを許さないのだと思います。コンパイラーで警告されるので、警告に従い「!」をつけました。
最後にNumberFormatteで数字表記に変換します。
print(String(formatter.string(from: nsNumberValue)!))
ここではString()はnilを許していないのかと思います。こちらもコンパイラーに指摘されるので「!」をつけています。
ちなみに上の記述で「formatter」はNumberFormatterのインスタンスのことで、利用する前に様々なプロパティを設定してフォーマットを決めていく必要があります。
ここでは暫定的に以下のものとしました。
let formatter = NumberFormatter()
// スタイルを指定
formatter.numberStyle = .decimal
// 数値の区切り文字を指定する
formatter.groupingSeparator = ","
// 何桁ごとに区切り文字を入れるか指定する
formatter.groupingSize = 3
formatter.locale = Locale(identifier:"ja_JP")
formatter.minimumFractionDigits = 10
これらについては追ってつめていきたいと思います。Localeの設定をしているので、上の,と3は不要な気もします。
実行結果の一例です。0が10個表示されるのはどうにかしたいところです。元が文字列の数字ですので、小数点以下の数字の個数がわかればどうにかなりそうです。
1
1.0000000000
12
12.0000000000
123
123.0000000000
1234
1,234.0000000000
12345
12,345.0000000000
12345.
12,345.0000000000
12345.6
12,345.6000000000
12345.67
12,345.6700000000
12345.678
12,345.6780000000
12345.6789
12,345.6789000000
12345.678
12345.67
12345.6
12345.
12345
1234
123
12
1
そこで、formatterの小数点以下の数値の数を以下のように設定してみました。
if let range = val.range(of: "."){
let underDicimal = val.count - 1 - val.distance(from: val.startIndex, to:range.lowerBound)
formatter.minimumFractionDigits = underDicimal
print(underDicimal)
}
ちなみに、小数点以下の長さを-1してますけど、val.countは1からの数になりますが、範囲型は0からの数になるようで、val.countから1を引いてあげる必要があるようです。
1
12
12
123
123
1234
1,234
12345
12,345
12345.
12,345
12345.6
1
12,345.6
12345.67
2
12,345.67
12345.678
3
12,345.678
12345.6789
4
12,345.6789
12345.678
12345.67
12345.6
12345.
12345
1234
123
12
1
0 件のコメント:
コメントを投稿