Open8

NumberFormatException

ykwsykws

次のコードを実行するとどうなるでしょうか?

"80000000".toInt(radix = 16)
ykwsykws

NumberFormatExceptionthrow されます

Exception in thread "main" java.lang.NumberFormatException: For input string: "80000000" under radix 16
 at java.lang.NumberFormatException.forInputString (:-1) 
 at java.lang.Integer.parseInt (:-1) 
 at FileKt.main (File.kt:7) 
ykwsykws

理由は Int.MAX_VALUE2147483647 で 16進数表記で 7FFFFFFF(16) なので、 8000000(16) は Int.MAX_VALUE を超えてしまうからです。

ykwsykws

ちなみにこれと同じような表現を Dart と Swift で書くとどうなるでしょうか?

Dart

int.parse('80000000', radix: 16);

https://api.flutter.dev/flutter/dart-core/int/parse.html

Swift

Int("80000000", radix: 16)

https://developer.apple.com/documentation/swift/int/init(_:radix:)

いずれも 2147483648 に変換されます。
どちらも 64bit なので Int の最大値は 9,223,372,036,854,775,807 になります。
16進数表記で 7FFFFFFFFFFFFFFF(16) なので、 8000000000000000(16) で最大値を超えます。

ykwsykws

Swift は Int の最大値を超えると nil を返します。

一方、 Dart は 9223372036854776000 という中途半端な数値を返します。
DartPad で試しているので、この制限かもしれません。

If the source string does not contain a valid integer literal, optionally prefixed by a sign, a FormatException is thrown.

FormatExceptionthrow されそうですが、確認できていないです。

ykwsykws

さて、戻って Kotlin では toInt の内部では Java の Integer.parseInt が呼ばれて、 NumberFormatExceptionthrow しています。

https://developer.android.com/reference/java/lang/Integer#parseInt(java.lang.String, int)

回避としては、

  1. toIntOrNull
  2. toLong

toIntOrNull

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/to-int-or-null.html

Int.MAX_VALUE2147483647 を超えたら null を返すようにします。 null かどうかを Kotlin で扱うのは次のように安全に扱えます。

"80000000".toIntOrNull(radix = 16)?.let { /* process */ }

toLong

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/to-long.html

Long.MAX_VALUE 9,223,372,036,854,775,807 まで扱えるようになりますが、これを超えると NumberFormatException を避けられません。

ykwsykws

Swift Int は正確にはプラットフォームに依存するため、 32-bit 環境なら同様の問題に直面してました

On 32-bit platforms, Int is the same size as Int32, and on 64-bit platforms, Int is the same size as Int64.