正解は
整数かどうかを調べるメソッド
Number.isInteger(num);
終わりです。
まさに整数(Integer)かどうかを調べるisInteger
メソッドがNumber
オブジェクトにあるのでそれを使えば良いです。
もう一つ、Number
オブジェクトには大きな数値を扱う時用の整数かどうかを調べるメソッドがあります
Number.isSafeInteger(num);
このisSafeInteger
メソッドは数値が安全な整数かどうかを判定します。
「安全な整数」とは-(2^53 - 1) 以上 2^53 - 1 以下を指します。
これらはつまりNumber.MIN_SAFE_INTEGER
とNumber.MAX_SAFE_INTEGER
の間ということで、
この間の整数であれば丸め誤差なく計算処理することが可能です。
整数かどうかだけが知りたいならこの二つで事足ります。
ですが、今回はjsを駆使?してこれら以外の方法で整数かどうかを判定する方法を考えます。
その他のNumberオブジェクトのメソッドを使う
01: parseInt
を使う
num === parseInt(num, 10);
parseInt
メソッドはグローバル関数の一つでNumber.parseInt
メソッドと同義です。
第1引数に指定された数値様文字列を、第2引数に指定された数値を基数とした整数に変換します。
第1引数が文字列型でなかった場合、文字列に変換してから評価します。
整数でなかった場合、左辺は非整数、右辺は整数となるので、
結果整数かどうかを判別することができます。
02: toFixed
を使う
num === Number(num.toFixed());
toFixed
メソッドは与えられた数値を固定小数点表記を用いて表した文字列に変換します。
引数は固定小数点の桁の数ですが無視すると0
となり結果小数部が消失し整数になります。
ただし文字列化しているので、これをNumber()
を使って数値に戻せば下の数値と比較できます。
Mathオブジェクトのメソッドを使う
03〜05: 数値丸めを使う
num === Math.floor(num);
num === Math.ceil(num);
num === Math.round(num);
Math
オブジェクトのfloor
、ceil
、round
の各メソッドは、
切り捨て、切り上げ、四捨五入といった数値の丸め処理をするメソッドです。
どんな形であれ、小数部がある場合これを削除し整数化するため、
元の数と比べれば異なる数値になり、結果整数かどうかの判定ができます。
06: trunc
を使う
num === Math.trunc(num);
trunc
メソッドは数値の少数部を取り除くためのメソッドです。
floor
に似ていますが、負の数の場合、floor
がマイナス方向に切り捨てるのに対して、
trunc
は(結果として)プラス方向に切り上げることになります。
Math.floor(-2.5); // -> -3
Math.trunc(-2.5); // -> -2
いずれにしても上記の丸め処理と同じように整数かどうかの判定に利用できます。
ビット演算を利用する
ビット演算を行うとき、扱う数値は強制的に整数化されます。
これを利用すれば与えられた数値が整数かどうかの判定に利用できます。
問題は元の値と(小数部以外が)変わらないビット演算を行えるかどうかです。
07: ビット演算子|
(ビット論理和)を使う
num === (num | 0);
ビット論理和は左右のビットのいずれかが1ならば1を返します。
従って片方が0のビット論理和はもう片方に影響を与えません。
ただしビット演算を行ったことにより整数化はされているので、
元の値と比べれば整数かどうかが判定できます。
08: ビット演算子~
(ビット否定)を使う
num === ~~num;
ビット否定は各ビットの1を0に、0を1に、というビット反転を行います。
従ってビット否定を2回行うと元の値に戻ります。
ただしビット演算を行ったことにより整数化はされているので、
元の値と比べれば整数かどうかが判定できます。
09: ビット演算子&
(ビット論理積)を使う
num === (num & -1);
ビット論理積は左右のビットのいずれもが 1 である時のみ1を返します。
従って片方が常に1であるビット論理積はもう片方に影響を与えません。
全てのビットが1で埋まった状態は-1
です(全てのビットが0である0
のビット否定です)。
上に同じくビット演算を行ったことにより整数化はされているので、
元の値と比べれば整数かどうかが判定できます。
10: ビットシフトを使う
num === num << 1 >> 1;
ビットシフトはビットの位置を全体的に右か左にずらす処理を行います。
ズレてあふれたビットは破棄されます。
左ビットシフトと右ビットシフトを同じ桁数行えば値は変わりませんが整数化はされます。
ただし(2 ** 30 - 1) = 1073741823
を超えるような数を左ビットシフトしようとすると
1ビットが溢れるので計算が正しくなくなります。
その他
11: 文字列に直して判定する
String(num).indexOf('.') === -1;
数値を文字列化した時小数点の「.」は入っていれば整数ではないと判断できます。
数値として4.00000
のような値を入れたとしてもString
が処理される前に、
4
に変換されるので整数と判断できます。
12: 剰余で判定する
num % 1 === 0;
正負どちらでも整数は1で割り切れるのであまりがないことで整数と判断できます。
13: 16進整数リテラルを利用して判定する
!isNaN(Number('0x' + Math.abs(num)));
16進整数リテラルは接頭辞「0x」に続き16進数の整数を書くことで数値と判断します。
小数点を受け付けないのでこれで小数部があるかどうかを判別することができます。
元の値が負数の場合は絶対値化してから判断します。
14: Arrayコンストラクターを利用して判定する
try {
Array(Math.abs(num));
return true;
} catch (error) {
return false;
}
新しい配列(Arrayオブジェクト)を生成するためのArrayコンストラクターは、
配列の長さを引数に数値で指定して生成することができます。
この時の引数として受け付けられる数値は1から2 ** 32 - 1 = 4294967295
までの
正の整数であり、それ以外はRange Error
を返します。
なのでこの処理をtry...catch
文でラップすれば整数かどうかを判定できます。