#teratail_kt
にて(UbuntuにKotlinをインストールしてハローワールドまでやってみた #teratail_kt)から引き続き。
FizzBazzだけだとつまらないので35で割り切れる場合にWith B
にします。
それだけなんだけど結構勉強になりました。
通常のFizzBazz
fun main(args: Array<String>) {
for (i in 1..100) {
when {
i % 15 == 0 -> println("FizzBuzz")
i % 3 == 0 -> println("Fizz")
i % 5 == 0 -> println("Buzz")
else -> println(i)
}
}
}
実行すると数字が100までカウントアップしていきFizzのときとBazzのときとFizzBazzのときは表示が変わります。
1
2
Fizz
4
Buzz
Fizz
7
Kotlinで35億を扱う
上記コードでそのまま35億(3500000000
)を扱おうとしてみます。
fun main(args: Array<String>) {
for (i in 1..3500000000) {
when {
i % 15 == 0 -> println("FizzBuzz")
i % 3 == 0 -> println("Fizz")
i % 5 == 0 -> println("Buzz")
else -> println(i)
}
}
}
エラーになりました。Intの桁数っぽいですね。
$ kotlinc ./35.kt -include-runtime -d 35.jar
35.kt:4:13: error: operator '==' cannot be applied to 'Long' and 'Int'
i % 15 == 0 -> println("FizzBuzz")
^
35.kt:5:13: error: operator '==' cannot be applied to 'Long' and 'Int'
i % 3 == 0 -> println("Fizz")
^
35.kt:6:13: error: operator '==' cannot be applied to 'Long' and 'Int'
i % 5 == 0 -> println("Buzz")
^
型推論で変数iがInt型になっていますが、KotlinのInt型が32ビットということで範囲外のようです。
32ビット - Wikipedia
32ビットアーキテクチャ 32ビットに格納できる符号なし整数の範囲は、0 から 4,294,967,295 である。 2の補数で表現できる符号付き整数は −2,147,483,648 から 2,147,483,647 を格納できる。
KotlinのIntの最大値を調べてみる
Int.MAX_VALUEで調べることができます。
fun main(args: Array<String>) {
println(Int.MAX_VALUE)
}
$ kotlinc ./maxint.kt -include-runtime -d maxint.jar
$ kotlin maxint.jar
2147483647
実行すると2147483647
が最大値ということが分かります。
ブルゾンちえみ風に言うと 21億と4000万ですね。
つまり35億はそのままでは扱えません。
ちなみに調べたら最初にあたったこちらの記事でJavaだとSystem.out.println(Integer.MAX_VALUE);
で調べられるとあったのでKotlinのコードの中にそのまま記載してみましたが、問題なく動いてました。
やはり歴史的にJavaは記事の文献がかなり多いので、検索ヒットしやすいです。
Javaで調べつつそのコードをKotlinで試すというのがやりやすいかもと思いました。
Javaのコードがそのまま動くKotlinの利点ですね。
fun main(args: Array<String>) {
System.out.println(Integer.MAX_VALUE);
}
Int型ではなくLong型を使う
ということでLong型を利用します。
fun main(args: Array<String>) {
var i: Long = 3500000000
println(i)
}
$ kotlinc ./35.kt -include-runtime -d 35.jar
$ kotlin 35.jar
3500000000
ちゃんと35億が表示されました。
35億の剰余演算(%)
まだ剰余演算で課題があります。
fun main(args: Array<String>) {
var input: Long = 3500000000
val malePopulation: Long = 3500000000 //世界中の男
if(input % malePopulation == 0){
println("35億")
}
}
35.kt:5:8: error: operator '==' cannot be applied to 'Long' and 'Int'
if(input % malePopulation == 0){
^
この表記の場合0がIntと判定されてしまう模様です。
toLong()
でキャストすることで回避できます。
fun main(args: Array<String>) {
val input: Long = 3500000000
val malePopulation: Long = 3500000000 //世界中の男
if(input % malePopulation == 0.toLong()){
println("35億")
}
}
35億のときにブルゾンちえみ With B
するFizzBazz
改めて仕様です。
- 3で割り切れる時は"Fizz"
- 5で割り切れる時は"Bazz"
- 3でも5でも割り切れるときは"FizzBazz"
- 35億で割り切れる時は"With B"
fun main(args: Array<String>) {
val malePopulation: Long = 3500000000 //世界中の男
for (i in 1..malePopulation) {
when {
i % malePopulation == 0.toLong() -> println("With B")
i % 15 == 0.toLong() -> println("FizzBuzz")
i % 3 == 0.toLong() -> println("Fizz")
i % 5 == 0.toLong() -> println("Buzz")
else -> println(i)
}
}
}
さて実行ですが、 35億ループを回すのでめっちゃ時間かかります。 苦笑
何分くらいかかるのか執筆しながら検証中...
FizzBazzを引数入力に対応させる
for文使うと処理時間的に大変なので、引数入力に対応させます。
main()の引数args
で利用可能みたいです。
kotlin hello.jar 35
など実行時に引数を指定するとprintln(args[0])
で取得できます。
fun main(args: Array<String>) {
println("input:" + args[0])
val i: Long = args[0].toLong()
val malePopulation: Long = 3500000000 //世界中の男
when {
i % malePopulation == 0.toLong() -> println("with B")
i % 15 == 0.toLong() -> println("fizzbuzz")
i % 3 == 0.toLong() -> println("fizz")
i % 5 == 0.toLong() -> println("buzz")
else -> println("特に無し")
}
}
結果
$ kotlin 35fizzbazz.jar 2
input:2
特に無し
$ kotlin 35fizzbazz.jar 3
input:3
fizz
$ kotlin 35fizzbazz.jar 5
input:5
buzz
$ kotlin 35fizzbazz.jar 15
input:15
fizzbuzz
$ kotlin 35fizzbazz.jar 3500000000
input:3500000000
with B
お疲れ様でした。
所感
FizzBazzも桁数が増えるとハマりどころあるんですね。
Intだけでは出来ないってあたりに学びありだし、処理時間かかりすぎるので引数の取り方も覚えたし...あとJavaでの整数最大値のInteger.MAX_VALUE
とJavaコードとKotlinの併用も
なんとなく思いついた35億ネタだけど35億はキャスト周りを教えるネタとしてはとっつきやすくてよいネタかもとか思ったりしました。笑