JavaScript

Number(数値)

 多くのプログラミング言語と違って、JavaScriptでは、整数と浮動少数点数を区別しません。すべての数値を浮動小数点数の Number型で表します。Number型は、-(253 - 1) から 253 - 1 までの数値は正確に表現できます。この範囲外の整数を使った場合には、下位数値の精度が損なわれます。ただし、配列のインデックス指定や、ビット演算子のように、32ビット整数として処理されるものもあります。また、数値の先頭に 0b、0o、0xなどを付けることによって、10進数以外も表現できます。

10進数
0〜9の10種類の数字で数値を表現。
(例:1234、0.5、.5)
2進数
0、1の2種類の数字で数値を表現。
(例:0b11、0B11)
8進数
0〜7の8種類の数字で数値を表現。
(例:0o11、0O11、011)
16進数
0〜9の10種類の数字と A〜Fの6種類のアルファベットで数値を表現。
(0x11、0X11)

10進数

 10進数で数値を表す場合には、0以外の数値から始めます。(0から始めた場合には、8進数と認識されるので、注意してください)

 また、次のように、浮動小数点リテラル(.)を使うことで、小数点以下の数値を表現できます。この場合には、0.5のように 0 から始めても10進数と認識されます。なお、浮動小数点の先頭の 0 は省略することもできます。

浮動小数点の記述例


console.log( 1234 + 0.5 );
> 1234.5

console.log( 1234 + .5 );
> 1234.5

 また、数値に e に続けて数値を記入した場合には、10数値を表します。

e に続けて数値を記入した場合


console.log( 3e4 );
> 30000 ----- 3 * 10 * 10 * 10 * 10

2進数

 先頭に 0b または 0B を付けることで、2進数で数値を表します。

2進数の記述例


console.log( 0b11 );
> 3 ----- 10進数では 3 と同値

8進数

 先頭に 0o、0O(ゼロオー)または 0(ゼロ)を付けることで、8進数で数値を表します。

8進数の記述例


console.log( 0o11 );
> 9 ----- 10進数では 9 と同値

16進数

 先頭に 0x または 0X を付けて、数字の0〜9、アルファベットのa〜f(大文字でも可)を続けることで、16進数で数値を表します。

16進数の記述例


console.log( 0x11 );
> 17 ----- 10進数では 17 と同値


 JavaScriptプログラム内に直接記述されている数字を数値リテラルと言います。これから、JavaScriptがサポートする数値リテラルの種類について説明します。なお、すべての数値リテラルに対して、その前にマイナス記号( - )を記述することで符号を反転できます。ただし、このマイナス記号は、JavaScriptの仕様上は単項演算子と見なされ、数値リテラルの一部ではありません。

浮動小数点リテラル

 次のように、浮動小数点リテラル( . )を使うことで、小数点以下の数値を表現できます。この場合には、0.5 のように 0 から始めても10進数と認識されます。なお、不動小数点の先頭の 0 は省略することもできます。

 浮動小数点リテラルでは小数部や指数も使用できます。浮動小数点リテラルは、先頭が整数部、その次に小数点、その後ろに小数部という形式で記述します。

 指数は、先頭が英字の e または E、その次にプラス( + )またはマイナス( - )記号(これはあってもなくてもかまいません)、その次に整数指数という形式で、小数部の後ろに記述します。浮動小数点リテラルの値は、先行する整数部と小数部の数値に 10 を指数部で指定された回数だけ掛けた値になります。

 書式は次のとおりです。


[ 数値 ][ .数値 ][ (E|e) [ (+|-) ] 数値 ]

 実例を以下にいくつか挙げます。


3.14
2345.789
.333333333333333333

6.02e23    // 6.02 × 1023

1.4738223E-32    // 1.4738223 × 10-32

整数リテラル

 整数を 16進数で指定することもできます。16進リテラルは、先頭が 0x または 0X 、その後に一連の 16進数値が続きます。16進数値は 0 から 9 までの数字と a (または A )から f (または F )までの英字です。この英字は 10進数の 10 から 15 に対応します。16進リテラルの例をいくつか示しましょう。


0xff
// 15*16 + 15 = 255 (10進)

oxCAFE911

 ECMAScript 標準では 8進リテラルはサポートされていません。しかしながら、JavaScript の処理系によってはサポートされている場合があるので紹介しておきます。8進リテラルは、先頭がゼロで、その後に一連の数値( 0 から 7 まで)が続きます。例を示しましょう。


0377
// 3*64 + 7*8 + 7 = 255 (10進)

 8進リテラルは、JavaScript の処理系によってサポートされていたり、サポートされていなかったりします。つまり、0 から始まる整数を記述すると、処理系によって 8進数として解釈されたり、10進数として解釈されたりするので、0 から始まる整数は使わないようにしてください。ECMAScript 5 の strictモードでは、8進数を使えません。

数値計算で利用する演算子

 数値計算では、下表の演算子を使用できます。比較的なじみ深いものばかりなので、覚えておくようにしましょう。

記号 演算の種類 結果
+ 加算 6 + 9 15
- 減算 20 - 15 5
* 乗算 3 * 7 21
/ 除算 10 / 5 2
% 剰余 7 % 3 1(7を3で割ったときの余り)
** べき乗 3 ** 2 9(3の2乗)

 これらの基本的な算術演算子の他に、もっと複雑な数学演算を行う関数がたくさんあります。これらの関数は、Math という名前のオブジェクトのプロパティとしてコア言語に組み込まれています。以下に例を示します。


Math.pow(2,53)
// => 9007199254740992: 2 の 53 乗。

Math.round(.6)
// => 1.0: 最近傍の整数に変換。

Math.ceil(.6)
// => 1.0: 整数に切り上げ。

Math.floor(.6)
// => 0.0: 整数に切り捨て

Math.abs(-5)
// => 5: 絶対値。

Math.max(x,y,z)
// 引数の中から最大値を返す。

Math.min(x,y,z)
// 引数の中から最小値を返す。

Math.random()
// 0 以上 1.0 未満の擬似乱数を返す。

Math.PI
// π : 円周率。

Math.E
// e: 自然対数の底。

Math.sqrt(3)
// 3 の平方根。

Math.pow(3,1/3)
// 3 の立方根。

Math.sin(0)
// 三角関数。Math.cos や Math.atan なども。

Math.log(10)
// 10 の自然対数。

Math.log(100)/Math.LN10
// 底が 10 の 100 の対数(100 の常用対数)。

Math.log(512)/Math.LN2
// 底が 2 の 512 の対数。

Math.exp(3)
// Math.E の 3 乗。

 JavaScript では、算術演算中にオーバーフローやアンダーフローが発生した場合や、0除算を行った場合もエラーが発生しません。算術演算の結果が表現可能な最大値より大きくなった場合(オーバーフロー)、算術演算の結果は無限大という特殊な値になります。JavaScript がこの値を出力する場合は、「 Infinity 」と出力します。同様に、ある負数の絶対値が表現可能な最大値を超えた場合、演算結果は特殊な無限大負値になります。JavaScript がこの値を出力する場合は、「 -Infinity 」と出力します。無限大値にどんな値を加算しても、減算しても、乗算しても、除算しても、無限大値のままです(符号が変わる場合はあります)。

 算術演算の結果の絶対値が表現可能な最小値よりも 0 に近づいた場合に、アンダーフローが発生します。この場合、JavaScript は 0 を返します。負の値に対してアンダーフローが発生した場合は、JavaScript は「負の 0 」という特殊な値を返します。この「負の 0 」は通常の 0 とほとんど区別がつかないので、JavaScript プログラマは気にする必要はありません。

 0 除算も JavaScript ではエラーにはなりません。無限大や、負の無限大が返されるだけです。しかし、1つだけ例外があります。それは 0 を 0 で割った時です。この計算結果は不定となり、JavaScript がこの値を出力する場合「 NaN 」(not-a-number)と出力します。無限大を無限大で割った場合や、負数の平方根を求めた場合、数値に変換できないオペランドに対して算術演算を行った場合にも NaN という結果になります。

 JavaScript には、InfinityNaN というグローバル変数があらかじめ定義されています。それぞれ、正の無限大と不定値(not-a-number)が格納されています。ECMAScript 3 では、この 2つのグローバル変数は読み書きできます。つまり、値を変更できます。ECMAScript 5 では、この問題は修正されました。値の読み出しのみとなり、変更できなくなっています。Number オブジェクトにも同様のプロパティが存在します。こちらは、ECMAScript 3 でも読み出しのみで変更はできません。以下に例をいくつか紹介します。


Infinity
// 読み書き可能な変数。初期値は無限大。

Number.POSITIVE_INFINITY
// 同じく無限大。読み出しのみ。

1/0
// この式も無限大を返す。

Number.MAX_VALUE + 1
// この計算も無限大になる。

Number.NEGATIVE_INFINITY
// 以下の式は、負の無限大になる。
 	-Infinity
 	-1/0
 	-Number.MAX_VALUE - 1

NaN
// 読み書き可能な変数。初期値は NaN。

Number.NaN
// 同じく NaN。読み出しのみ。

0/0
// この式は NaN と評価される。

Number.MIN_VALUE/2
// アンダーフローが発生し 0 になる。

-Number.MIN_VALUE/2
// 負の 0。
 	-1/Infinity
 	// これも負の 0。
 	-0

 JavaScript の NaN 値には、どの値と比較しても等しいと判定されない。という特徴があります。NaN 値同士を比べても等しいと判定されません。つまり、x == NaN と記述しても、ある変数 x の値が、NaN 値かどうかを判定できないということです。代わりに、x != x と記述してください。この式は、xNaN 値の時だけ、true になります。isNaN() 関数でも調べられます。この関数は、引数が NaN か、もしくは文字列やオブジェクトなどの数値以外の値の場合に、true を返します。同じように、isFinite() 関数は、引数が NaNInfinite-Infinite 以外の数値の場合に、true を返します。

 負の 0 にも少し特徴があります。負の 0 は、通常の 0 と等しいと判定されます。JavaScript の同値演算子でも等しいと判定されるので、事実上区別することはできません。ただし、除算で使った時にだけ違いが生じます。


var zero = 0;
// 通常の 0 。

var negz = -0;
// 負の 0 。

zero === negz
// => true: 通常の 0 と負の 0 は等しい。

1/zero === 1/negz
// => false: 無限大と負の無限大は等しくない。

2進浮動小数点と丸め誤差

 実数は無限に存在します。しかし、JavaScript の浮動小数点形式では、有限個(正確には、18437736874454810627個)しか表現出来ません。つまり、JavaScript で実数を処理する場合、実数を近似表現することになる場合がほとんどです。

 JavaScript をはじめとして、最近のプログラミング言語の大半で使われている IEEE-754 浮動小数点表現形式は、2進数表記ですので、1/2 や 1/8 、1/1024 などの小数は正確に表現出来ます。しかし、金融計算などで普段使っているのは 1/10 、1/100 などの 10進数です。2進浮動小数点表現形式では、0.1 のような値も正確には表現できません。

 JavaScript の数値の精度は十分高いので、0.1 をほぼ近似表現できます。しかし、数値を正確に表現できないために、問題が生じる場合もあります。次のコードを見てください。


var x = .3 - .2;
// 30 セントから 20 セントを減算する。

var y = .2 - .1;
// 20 セントから 10 セントを減算する。

x == y
// => false: 2つの値は同じではない。

x == .1
// => false: .3 - .2 は .1 と等しくない。

y == .1
// => true: .2 - .1 は .1 と等しい。

 丸め誤差のために、.3 と .2 の差分の近似表現と、.2 と .1 の差分の近似表現は正確には同じ値になりません。なお、この問題は、JavaScript 特有の問題ではないことをよく覚えておいてください。2進浮動小数点数値を使うプログラミング言語なら同じような問題が生じます。また、先ほど紹介したコードの x と y の値はほぼ同じで、両方とも正しい値に非常に近い値になっています。計算結果が問題となる場合はほとんどありません。等しいかどうかを比較しようとした時にだけ問題が生じます。

 将来的には、JavaScript が 10進数型をサポートするようになり、前述したような丸め誤差問題も解決するかもしれません。ただ、それまでは、重要な金融計算では、スケールを調整して整数を使うようにしてください。例えば、先程の例であれば、ドル単位で計算する代わりに、セント単位で計算するとよいでしょう。

日付と時刻

 コア JavaScript 言語には、日付と時刻を表現するオブジェクトを生成するために、Date() コンストラクタが用意されています。Date オブジェクトには、日付計算を行うための API がメソッド形式で提供されています。Date オブジェクトは、数値型などのような基本型ではありません。この項では、日付処理の概要についてだけ説明します。


var then = new Date(2013, 6, 27);
// 2013年7月27日。

var later = new Date(2013, 6, 27, 17, 10, 30);
// 2013年7月27日現地時間午後5:10:30。

var now = new Date();
// 現在の日付と時刻。

var elapsed = now - then;
// Date 型の減算。ミリ秒単位の間隔。

later.getFullYear()
// => 2013

later.getMonth()
// => 6: 1月を 0 とする月番号。

later.getDate()
// => 27: 1日を 1 とする日にち。

later.getDay()
// => 6: 曜日。0 が日曜日、6 が土曜日。

later.getHours()
// => 17: 現地時間午後 5時。

later.getUTCHours()
// UTC での時間。タイムゾーンに依存する。

later.toString()
// => "Sat Jul 27 2013 17:10:30 GMT-0800 (PST)"

later.toUTCString()
// => "Sun, 28 Jul 2013 01:10:30 GMT"

later.toLocaleDateString()
// => "27/07/2013"

later.toLocaleTimeString()
// => "05:10:30 PM"

later.toISOString()
// => "2013-07-28T01:10:30.000Z" : ES5 のみ。