【STEP.17】
JavaScriptの数値操作・数学演算をマスターしよう!

数値操作

Numberオブジェクトとは

Numberオブジェクトは、数値型(number型)の値を扱うためのラッパーオブジェクトで、数値を整形するための機能を提供するとともに、無限大/無限小、数値型の最大値/最小値など、特別な値を表すための読み取り専用プロパティ(定数)を公開しています。

Numberオブジェクトのメンバー一覧

Numberオブジェクトのメンバーには次に掲げる表のようなものがあります。

【Numberオブジェクトの主なメンバー(*は静的メソッド)】
分類メンバー概要
プロパティ*MAX_VALUENumberで表せる最大の値
(1.7976931348623157e+308)
*MAX_SAFE_INTEGER
ES2015
Numberで安全に表せる最大の整数値
(9007199254740991)
*MIN_VALUENumberで表せるゼロに近い整数
(5e-324)
*MIN_SAFE_INTEGER
ES2015
Numberで安全に表せる最小の整数値
(-9007199254740991)
*EPSILON
ES2015
1と、Numberで表せる1より大きい最小の値との差
(2.220446049250313e-16)
*NaN数値でない(Not a Number)
*NEGATIVE_INFINITY負の無限大
*POSITIVE_INFINITY正の無限大
メソッドtoString(rad)rad進数の値に変換(radは2~36)
toExponential(dec)指数形式に変換(decは小数点以下の桁数)
toFixed(dec)小数点第dec位になるよう四捨五入
toPrecision(dec)指定桁数に変換(桁数が不足する場合は0で補う。)
*isNaN(num)
ES2015
Nan(Not a Number)であるかを判定
*isFinite(num)
ES2015
有限値であるかを判定
*isInteger(num)
ES2015
整数値であるかを判定
*isSafeInteger(num)
ES2015
Safe Integerであるか(正しくIEEE-754倍精度数として表現できるか)を判定
*parseFloat(str)
ES2015
文字列strを小数点数に変換
*parseInt(str [.radix])
ES2015
文字列strを整数に変換(引数radixは基数)

Numberオブジェクトの定数

POSITIVE_INFINITYNEGATIVE_INFINITYNaNはいずれも特殊な数値(定数)を表します。

POSITIVE_INFINITYNEGATIVE_INFINITY(無限大)は、ある演算の結果が、JavaScriptで表現可能な数値の範囲を超えた場合の戻り値として利用されます。

一方、NaN(Not a Number)は、たとえば「0を0で除算した」など不正な演算が行われた場合などに、数値として表現できない結果を表すために使用されます。

MAX_SAFE_INTEGERMIN_SAFE_INTEGERは、JavaScriptで安全に演算できる範囲の整数値の上限/下限を表します。

上限下限を超えた演算は、結果も保証されません。

console.log(Number.MAX_SAFE_INTEGER);
// 結果:9007199254740991

console.log(Number.MAX_SAFE_INTEGER + 1);
// 結果:9007199254740992

console.log(Number.MAX_SAFE_INTEGER + 2);
// 結果:9007199254740992(不正)

n進数を求める【toString】

NumberオブジェクトのtoStringメソッドを基数付きで呼び出します。

基数には2~36を指定できます。

10を超えた場合には、各桁はa~zで表します(36は0~9、a~zで表せる最大の基数です)。

let num = 255;
console.log(num.toString(2));
// 結果:11111111
console.log(num.toString(16));
// 結果:ff
console.log(num.toString(36));
// 結果:73

任意の桁数で小数点数を丸める【toFixed/toPrecision】

数値を整数にするのではなく、特定の桁位置で丸めたいという場合には、NumberオブジェクトのtoFixedtoPrecisionメソッドを利用します。

toFixedメソッドは、小数点以下が指定された桁数になるように丸めを行うのに対して、toPrecisionメソッドは、数値全体が指定された桁数になるように丸めます。

また、toFixedtoPrecisionメソッドはいずれも、指定の桁数に満たない場合は不足分をゼロで補います。

let num = 123.456;
console.log(num.toFixed(2));
// 結果:123.46
console.log(num.toFixed(5));
// 結果:123.45600
console.log(num.toPrecision(5));
// 結果:123.46
console.log(num.toPrecision(8));
// 結果:123.45600

文字列を数値に変換する【Number.parseInt/Number.parseFloat】

JavaScriptはデータ型に寛容な言語で、その時々の文脈(前後の関数や演算子)によって、操作対象の値を適切なデータ型に自動的に変換してくれます。

しかし、この自動変換が時として、思わぬバグの温床になるようなケースもあります。

そこで、JavaScriptではデータ型を明示的に変換するための方法を提供しています。

データ型を明確にしたうえで処理を行いたい場合、あるいは、変数の内容がそもそもあいまいである場合には、明示的にデータ型を変換することで、スクリプトの思わぬ挙動を未然に防ぐことができます。

Numberオブジェクトに含まれるparseIntparseFloatメソッドもデータ型を明示的に変換する方法のひとつです。

Number.parseIntparseFloatメソッドは、いずれも「与えられた値を数値に変換する」という点で共通しています。

しかし、細かな挙動は微妙に異なるので、要注意です。

具体的なサンプルを確認してみましょう。

文字列の混在した数値を渡した場合

まずは、文字列の混在した数値の変換例です。

// 文字列の混在した数値
let data1 = '888abc';
console.log(Number.parseInt(data1));
// 結果:888
console.log(Number.parseFloat(data1));
// 結果:888

888abc」のような文字列混在の数値も、数字として解析できる部分を先頭から取り出して変換します。

16進数と指数表現を渡した場合

次は、16進数と指数表現の変換例です。

// 16進数
let data2 = '0x10';
console.log(Number.parseInt(data2));
// 結果:16
console.log(Number.parseFloat(data2));
// 結果:0

// 指数表現
let data3 = '1.414E3';
console.log(Number.parseInt(data3));
// 結果:1
console.log(Number.parseFloat(data3));
// 結果:1414

parseFloatメソッドは16進数表現を認識できずに、 数字として解析できる部分を先頭から取り出した結果、0を返します。

逆に、parseIntメソッドは指数表現を認識できず、 数字として解析できる部分を先頭から取り出し、整数に変換した結果を返しています。

2、8進数表現を渡した場合

なお、ES2015で導入された2、8進数表現は、次のように正しく解析することができずに「0b~0o~」の前の0を返すだけです。

// 2進数
let data4 = '0b100';
console.log(Number.parseInt(data4));
// 結果:0
console.log(Number.parseFloat(data4));
// 結果:0

// 8進数
let data4 = '0o10';
console.log(Number.parseInt(data4));
// 結果:0
console.log(Number.parseFloat(data4));
// 結果:0

オブジェクトを渡した場合

次は、オブジェクトを渡した例です。

// オブジェクト
let data5 = new Date();
console.log(Number.parseInt(data5));
// 結果:NaN
console.log(Number.parseFloat(data5));
// 結果:NaN

オブジェクトが渡された場合には解析を諦めて単純に非数値(NaN)を返します。

MEMO
parseInt/parseFloat関数
Number.parseIntparseFloatメソッドは、ES2015で導入されたメソッドです。

ES2015より前では同名のグローバル関数parseIntparseFloatを利用します。

いずれも挙動は同じですが、数値関連の機能はNumberオブジェクトにまとまっていたほうがわかりやすいことから、そのように改められました。

数学演算

Mathオブジェクトとは

Numberオブジェクトはあくまで「数値型の値を直接操作するためのオブジェクト」であり、いわゆる指数表現や平方根、対数関数など、数学に関わる演算機能は持っていません。

数学演算の機能を提供するのが、Mathオブジェクトです。

Mathオブジェクトのメンバー一覧

Mathオブジェクトのメンバーには次に掲げる表のようなものがあります。

【Mathオブジェクトで利用可能なメンバー(*は読み取り専用)】
分類メンバー概要
基本abs(num)絶対値
clz32(num)ES201532ビットバイナリにおいて前にある0ビットの個数
max(num1,num2,…)num1,num2…で最も大きな値
min(num1,num2,…)num1,num2…で最も小さな値
pow(base,num)べき乗(値baseのnum乗)
random()0~1未満の乱数
sign(num)ES2015指定した値が整数の場合は1、負数の場合は-1、0の場合は0
切上/切捨ceil(num)小数点以下の切り上げ(引数num以上の最小の整数を取得)
floor(num)小数点以下の切り捨て(引数num以下の最大の整数を取得)
round(num)小数点以下の丸め(四捨五入)
trunc(num)ES2015小数点部分の単純な切り捨て(整数部分の切り出し)
平方根*SQRT1_21/2の平方根(0.7071067811865476)
*SQRT22の平方根(1.4142135623730951)
sqrt(num)平方根
cbrt(num)ES2015立方根
hypot(x1,x2,…)ES2015引数の二乗和の平方根
三角関数*PI円周率(3.141592653589793)
cos(num)コサイン
sin(num)サイン
tan(num)タンジェント
acos(num)アークコサイン
asin(num)アークサイン
atan(num)アークタンジェント
atan2(y,x)2変数のアークタンジェント
cosh(num)ES2015ハイパーポリックコサイン
sinh(num)ES2015ハイパーポリックサイン
tanh(num)ES2015ハイパーポリックタンジェント
acosh(x)ES2015ハイパーポリックアークコサイン
asinh(x)ES2015ハイパーポリックアークサイン
atanh(x)ES2015ハイパーポリックアークタンジェント
対数/指数関数*E自然対数の底(2.718281828459045)
*LN22の自然対数(0.6931471805599453)
*LN1010の自然対数(2.302585092994046)
*LOG2E2を底としたeの対数(1.4426950408889634)
*LOG10E10を底としたeの対数(0.4342944819032518)
log(num)自然対数
log10(num)ES2015底を10とする対数
log2(num)ES2015底を2とする対数
log1p(num)ES2015引数numに1を加えたものの自然対数
exp(num)指数関数(eの累乗)
expm1(num)ES2015enum-1
その他imul(a,b)ES2015高速な32ビット整数の乗算
fround(num)ES2015指定した値に最も近い単精度float値

Mathオブジェクトが提供するメンバーは、すべて静的プロパティ/メソッドである点に注意してください。

つまり、以下の形式で、Mathオブジェクトが提供するすべてのメンバーにアクセスできます。

Math.プロパティ名
Math.メソッド名(引数,...)

また、そもそもMathオブジェクトをnew演算子でインスタンス化することはできません。

たとえば、以下のような記述は、実行時エラーとなります。

let m = new Math();

小数点以下の数値で丸める【ceil/floor/round/trunc】

Mathオブジェクトに、次に掲げる表のようなメソッドが用意されています。

【数値を丸めるためのメソッド】
メソッド概要
ceil(num)小数点以下の切り上げ(引数num以上の最小の整数を取得)
floor(num)小数点以下の切り捨て(引数num以下の最大の整数を取得)
round(num)小数点以下の丸め(四捨五入)
trunc(num)小数点部分の単純な切り捨て(整数部分の切り出し)

ceil/floor/truncの違い

特に、負数の場合の結果に注目して、それぞれの例を確認してください。

負数の処理では、ceilfloorよりもtruncの挙動が直感的となっていることがわかります。

console.log(Math.ceil(1.56));
// 結果:2
console.log(Math.ceil(-1.56));
// 結果:-1
console.log(Math.floor(1.56));
// 結果:1
console.log(Math.floor(-1.56));
// 結果:-2
console.log(Math.round(1.56));
// 結果:2
console.log(Math.round(-1.56));
// 結果:-2
console.log(Math.trunc(1.56));
// 結果:1
console.log(Math.trunc(-1.56));
// 結果:-1

乱数を生成する【random】

Mathオブジェクトのrandomメソッドを利用します。

randomメソッドは0以上1未満の乱数を返します。

よって、たとえばminmaxの範囲の乱数を取得したいならば以下のようにします。

let min = 100;
let max = 200;
console.log(Math.floor(Math.random() * (max - min + 1)) + min);
// 結果:108(実行のたびに異なる数字が出力されます。)

よく利用する1~100の値であれば、より簡単に、以下のようにも表せます(上限を変えたいならば、以下のコードの「100」の部分を変更します)。

console.log(Math.floor(Math.random() * 100) + 1);
// 結果:45(実行のたびに異なる数字が出力されます。)

得られる結果は乱数なので、当然、実行のたびに異なります。

べき乗、平方根/立方根を求める【pow/sqrt/cbrt】

べき乗、平方根/立方根を計算するには、Mathオブジェクトの次に掲げる表のメソッドを利用します。

【べき乗、平方根/立方根のためのメソッド】
メソッド概要
pow(base,num)べき乗(baseのnum乗)
sqrt(num)平方根
cbrt(num)立方根ES2015

べき乗については、ES2016以降では**演算子を利用することもできます。

平方根も**演算子で「**0.5」のように表現できます。

console.log(Math.pow(2,3));
// 結果:8
console.log(2**3);
// 結果:8
console.log(Math.sqrt(36));
// 結果:6
console.log(36**0.5);
// 結果:6
console.log(Math.cbrt(64));
// 結果:4

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です