JavaScriptで次のことがしたい
- ある整数の数値がある
- その桁数が何桁か取得したい
たとえば 202309071056 という数値なら、
その桁数は12桁だよねという風な感じで…
でも誤った方法だと予期せぬ結果になります。
そこでそういったNG例なども踏まえて、
JSで数値桁数取得の正しい方法についてです。
NG例.数値を文字列変換してlengthから取得
数値の桁数取得のNG例から。
こういうのがググるとよく出てきます。
▼ 良さげに見えるけど実はよくない方法
1 2 3 4 5 |
const num = 202309071056; const digits = num.toString().length; console.log('桁数 : ', digits); /// => 桁数 : 12 |
この例だと上手くいってます。
単純に数値を文字列に変換し、その length から桁数取得するパターンですね。小さな数ならこの方法でもまったく問題ありません。
小さな数値なら…
21桁以上の整数は指数表記なのが厄介
上記の方法はなにが問題かという話です。
それは21桁~22桁以上は指数表記になること
これが桁数取得において障害になります。
▼ その根拠となる第三者の意見
21桁(値によって22桁)を超えた値を入力すると指数表記で表示されます。指数表記で表示された後、さらに値を入力すると小さな値に変更されてしまいます。これは、JavaScriptの小数値の精度に起因する制限事項です。
引用元 : https://developer-tools.zendesk.com/hc/ja/articles/360003998915
▼ 実際にChrome環境でも確かめてみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/// 21桁 console.log(100000000000000000000) /// => 100000000000000000000 /// 21桁 console.log(999999999999999000000) /// => 999999999999999000000 /// 21桁 console.log(999999999999999999999) /// => 1e+21 /// 22桁 console.log(100000000000000000000) /// => 1e+21 |
このように指数表記に切り替わります。
切り替わる境目というのは分からないけど、21桁~22桁のあいだのどこかです。指数表記の e+21 は「10の21乗」を表すという意味の表記です。
桁数取得にはこれも考慮しないといけません。
方法1.指数表記を考慮した桁数取得
ということで正しい方法を考えてみます。
以下のようなコードを作りました。
▼ このようなコード
1 2 3 4 5 6 7 8 9 10 11 |
/// 数値桁数を返す関数 function getNumDigits(num){ numStr = num.toString(); if(numStr.includes('e+')){ /// 指数表記なら指数桁+1を返す return parseInt(numStr.split('e+')[1])+1; }else{ /// 非指数表記ならそのまま返す return numStr.length; } } |
▼ いくつかの数で桁数取得を試す
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
console.log(getNumDigits( 202309071134 )); /// => 12 console.log(getNumDigits( 9876543210987654321098765 )); /// => 25 console.log(getNumDigits( 273335211246073180767438793192212499213 )); /// => 39 |
整数の桁数を求めることができます。
ただし上記関数では引数に非数(NaN)だったり少数が渡されたときのことは考えてません。飽くまで正の整数だけを考えてます。
方法2.BigIntによる桁数取得
もっと良い方法を見つけました。
それは BigInt を使うことです。
▼ BigIntとはなにか?
BigInt はプリミティブラッパーオブジェクトで、プリミティブの bigint 値、すなわち大きすぎて number プリミティブで表すことができない数を、表現したり操作したりするために使用します。
引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/BigInt
巨大数を扱うための型です。
正の整数のみという制約があるなら、
このBigIntで桁数取得するのが超簡単です。
▼ このような関数を定義する
1 2 3 |
function getNumDigits(num){ return BigInt(num).toString().length; } |
▼ いくつかの数で桁数取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/// 数値の桁数 console.log(getNumDigits( 2147483647 )); /// => 10 /// 数値の桁数 console.log(getNumDigits( 67280421310721 )); /// => 14 /// 数値を文字列として渡してもOK /// 数値が切り捨てされるのを防げる console.log(getNumDigits( '273335211246073180767438793192212499213' )); /// => 39 |
桁数取得が問題なくできてます。
最後の例では数値そのものではなく文字列で渡してます。これは 99999999999999999999 のような数だと切り捨てで 100000000000000000000 になるのを防ぐためです。
正確な桁数を知りたいならBigIntを使えばOK
以上、JSで数値桁数取得でした。ではまた