JavaScript で文字列を数値に変換する方法まとめ(加筆予定)
JavaScript で文字列を数値に変換する方法の例
-
parseInt(x, 10)=Number.parseInt(x, 10) -
parseFloat(x)=Number.parseFloat(x) Number(x)+x~~xx >>> 0-
valueAsNumber(input form の onChange コールバック関数のEventで)
実行結果のまとめ

("parseInt vs unary plus, when to use which? (Stackoverflow)" より)
仕様
parseFloat
parseFloat(x) の(やや雑な)動作概略:
-
をx で文字列に変換する(\mathrm{ToString} は文字列の場合はそのまま)x -
[1] で先頭の空白文字を除去する。\mathrm{TrimString}( \cdot , \mathrm{START}) -
の構文を満たす("-Infinity", "123_456", "12e+3" などにマッチする)最長の prefix を\mathit{StrDecimalLiteral} とする。もしそのような prefix が無ければ\mathit{trimmedPrefix} NaNを返す。 -
の\mathit{trimmedPrefix} を返す。\mathit{StringNumericValue}
まとめ
-
parseFloatは入力文字列の空白を除く先頭部分のみを数値として解釈する(" 123.45foo"→123.45) -
null,undefined,true,falseなどはいずれも、文字列化した結果の先頭に にマッチする部分が無いため\mathit{StrDecimalLiteral} NaNになる。 -
parseInt("0x100")は 256 だがparseFloat("0x100")は0になる。
parseInt
parseInt(x, radix) の(やや雑な)動作概略:
-
をx で文字列に変換する(\mathrm{ToString} は文字列の場合はそのまま)x -
[1:1] で先頭の空白文字を除去する。\mathrm{TrimString}( \cdot , \mathrm{START}) -
"-"始まりなら 、そうでなければ\mathit{sign} = -1 とする。\mathit{sign} = 1 - 先頭の
"-"や"+"文字を除いた部分文字列を とする。S - 基数 radix を
で 32bit 整数にマップする(\mathrm{ToInt32} InfinityやNaNは0にマップされ、小数は0方向に丸められる)。これを とする。R -
のときR = 0 とする。そうでないとき、R = 10 またはR < 2 のときは36 < R NaNを返す。 -
に「明示的に」値がセットされなかった場合やR の場合、R = 16 がS "0x"または"0X"で始まる文字列だった場合は とし、R = 16 から先頭2文字を取り除く。S - (TODO: 余力があれば追記)
-
をZ の最長の prefix であって "radix-S digit" からなるものとする。R - "radix-
digit" ...R 0-9a-zのうち、 番目までの文字のこと。例えばR ならR = 3 '0', '1', '2'、 ならR = 36 0-9a-zとなる。
- "radix-
-
が空文字ならZ NaNを返す。 -
を radix-\mathit{mathInt} 表記のR の整数値とする。Z -
(However, if R = 10 and Z contains more than 20 significant digits, every significant digit after the 20th may be replaced by a 0 digit, at the option of the implementation; and if R is not one of 2, 4, 8, 10, 16, or 32, then mathInt may be an implementation-approximated integer representing the integer value denoted by Z in radix-R notation.)
-
-
を返す。\mathit{sign} \times \mathit{mathInt}
まとめ
-
parseFloatと同様、入力文字列の空白を除く先頭部分のみを数値として解釈する(" 123.45foo"→123) - 正負は先頭の
"-"の有無だけで決まる。 - 0x, 0b など
-
parseIntは"0x"("0X")prefix を考慮する。 -
parseInt("0x1")は1に評価される。 -
parseInt("0x1", 16)は1に評価される。 -
parseInt("0x1", 36)は 1189 に評価される。('x'= 33 という文字として解釈される) -
parseInt("0z", 36)は35に評価される。 "0b111"は2進法表記の7としては解釈されず、 radix が 11 以下の場合 0、 radix が 12 以上の場合'b'= 12 という文字として解釈される。
-
-
parseFloatは0x始まりの文字列を解釈せず0に評価するが、parseIntは0x始まりの文字列を解釈できるので、parseIntはparseFloatの小数部無視バージョンではない。 - 細かい仕様
- radix に
36.9などを入れても36と解釈されて動く。1.9などは 2 未満で不正な入力扱いとなりNaNが返される。
- radix に
Number
Number(x) の(やや雑な)動作概略:
-
を\mathit{prim} とする。\mathrm{ToNumeric}(x)
加筆予定
valueAsNumber
type に
- number
- range
- date
- month
- week
- time
- datetime-local
のいずれかを付与している input 要素で使用可能( type="text" などの場合は数値を入力していても NaN になる)
import * as React from 'react';
const NumericInputExample = () => {
const [num, setNum] = React.useState(0);
const onChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setNum(ev.target.valueAsNumber);
},
[],
);
return (
<div>
<input type='number' value={num} onChange={onChange} />
<div>{num}</div>
</div>
);
};
(type="date" などのケースは本記事の調査対象外のため)type="number" の input 要素のイベントの場合を調べる。
parse アルゴリズムの仕様: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#rules-for-parsing-floating-point-number-values
valueAsNumber を計算する parse 処理の(やや雑な)動作概略:
\mathit{value} \gets 1 \mathit{divisor} \gets 1 \mathit{exponent} \gets 1 - 先頭の空白文字を無視する
-
'-'文字始まりなら を\mathit{divisor} に-1 - 先頭の
"-"や"+"文字を除いた部分文字列を とする。S - 以降加筆予定です 🙇♂️
使い分け方の考察
- 以下は
no-implicit-coercionや@typescript-eslint/restrict-plus-operandsで禁止して良さそう。-
+x(これは特に大体Number(x)と似た結果っぽいので、文字列連結構文との曖昧性回避のためにそちらを使う方が安全そう) ~~xx >>> 0
-
-
parseInt(x): 基数を設定したいときに使用できる。"11.9999999"とかは に評価されてしまうことなどに注意が必要そう。11 - 以下の三つはどれを使っても普通の浮動小数点数のパースには大体同じように使用できそうだが、若干
Numberか(使えるときは)valueAsNumberを使うのが無難そう?-
parseFloat(x)-
実用上は、
"123.foo"などの全体としては数値ではない文字列も prefix だけパースできてしまうことがある点に一番注意が必要かも。 うっかり渡すものを間違えてそのまま動いてしまうので気づかないという状況に注意したい。 -
"0x"始まりの文字列を解釈できない点にも注意が必要だが、そういう入力を受け付けることは実用上そんなに無い気もする。
-
実用上は、
-
Number(x)- 文字列は大体よしなに数値に変換してくれそうだが
true,false,nullなども や0 に評価して動いてしまう点に逆に注意が必要かも。ただし1 undefinedを渡すとNaNが返るところがややこしい。文字列入力想定ならこの辺は踏む心配は無い。 -
parseFloatと違い"123foo"とかはNaNになってくれるので fail fast の観点で安心。
- 文字列は大体よしなに数値に変換してくれそうだが
-
valueAsNumber- 想定している数値文字列に対しては
Number(x)と同じ挙動をしそう?(仕様要確認) - 数値入力欄のフォームに入力できる文字列を変換するロジックなので特に変な挙動は想定せず使えそう。
-
Number(event.target.value)とかわざわざするよりはevent.target.valueAsNumberを取り出した方が綺麗な気がする(パフォーマンスの細かい違いとかは調べ切れていない)。 - ただ
type="text"のときは常にNaNに評価されるので<input type="text">を数値入力欄として使っているときは使用できない。
- 想定している数値文字列に対しては
-
TypeScript で unknown 型の変数を数値に変換したいときは、 まず typeof で場合分けして string 以外のケースは用途に応じて適宜定義し、 string 型のケースに Number を使ってパースするのが一番安全そうかなと思いました。
Discussion