parseIntとparseFloatの覚え書き

前フリが思いつかない件について。
この記事の主旨は一言で言うと「parseIntには第2引数で基数を指定しよう」です。

基本

parseIntとparseFloatは、どちらも引数として渡された文字列をパースして数値に変換するグローバル関数。
parseIntは整数、parseFloatは小数と整数の両方(浮動小数点数)を扱える。

parseInt("100")    // 100
parseInt("3.14")   // 3

parseFloat("100")  // 100
parseFloat("3.14") // 3.14

パース方法とNaN

parseIntとparseFloatは、どちらも引数の文字列を先頭から1文字ずつ確認し、数値と解釈できない文字が見つかった時点で、その直前までの部分を数値として返す。
一文字も数値にできなかった場合はNaN(数値ではないことを表す数値型の値)を返す。

わかりにくいので例を。

parseInt("100pt")     // 100
parseInt("-3.14pt")   // -3
parseInt("314e-2")    // 314
parseInt("hoge123")   // NaN

parseFloat("100pt")   // 100
parseFloat("-3.14pt") // -3.14
parseFloat("314e-2")  // 3.14
parseFloat("hoge123") // NaN

parseFloatが数値と解釈できるのは、正負符号(+/-)、0〜9の数字、小数点、指数(e)。
parseIntはそこから小数点を除いたもの……ではなくて、実はもうちょっと複雑。

parseIntの第2引数(基数)

parseIntの引数として、パースしたい文字列のほかに、「何進数として解釈するか」という基数を渡すことができる。
基数は文字列でなくて数値で渡すことに注意。

parseInt("15", 10) // 15
parseInt("15", 8)  // 13
parseInt("15", 16) // 21

同じ"15"という文字列を、10進数、8進数、16進数でパースした値が返ってくる。

基数の指定によって、数として解釈できる文字は変わってくる。ちょっと複雑と言ったのはこのこと。

parseInt("19e", 10) // 19("e"はパース不可)
parseInt("19e", 8)  // 1 ("9e"はパース不可)
parseInt("19e", 16) // 414

基数を省略した場合、通常は10進数でパースされる。のだけど、省略するとけっこう危険だったりする。

基数を省略した場合

もしくは、基数に0を指定した場合、自動的に以下のように解釈されることが多い。

  • "0x"または"0X"で始まる文字列が渡された場合、基数は16(16進数)と解釈される。
  • "0"で始まる文字列が渡された場合、基数は8(8進数)と解釈される。
  • その他の文字で始まる文字列が渡された場合、基数は10(10進数)と解釈される。
parseInt("0x15") // 21(16進数として解釈)
parseInt("015")  // 13(8進数として解釈)※実装による
parseInt("15")   // 15(10進数として解釈)


16進数はともかく、この8進数がなかなか厄介で……

parseInt("015")  // 13(8進数)※実装による
parseInt("019")  // 1 (8進数、"9"はパース不可)※実装による
parseInt("08")   // 8 (8進数だとNaNになるので10進数で解釈)※実装による


あるでしょう、ノンブルとかで先頭をゼロで埋めてるやつ。
それをうっかりparseInt(textframe.contents)なんてやってしまうと、ページによって変な数値が返ってくる可能性があるということ。

余談

先頭の文字列が"0x"なら16進数、というのは、JavaScript(というか、ECMAScript)の仕様として規定されている。しかし実は先頭が"0"の場合は、「8進数にしてもいいよ(どっちかいうと10進数でやってね)」ということになっていた。
実装では8進数を採用したものが多いけど、確実ではないらしい。つまり実行する環境によって結果がまちまちということ。さっきから※実装によるって書いてるのはそういうことです。

いちおう現在の最新の仕様では、"0x"と"0X"を16進数とするのを除けばデフォルトは10進数、と定められている。けど実装のほうは今のところほとんど追いついてないらしい。AdobeのESTKでも8進数になるしね。

というわけで、この記事の主旨


parseIntには第2引数で基数を指定しよう


大事なことなので2回いいました。ちなみにparseFloatは常に10進数で、基数指定はできません。