JavaScript勉強会

JavaScriptの学習日記

4.4 小数点第◯位で切り捨てる 《Mathオブジェクト》 【JavaScript超入門】

JavaScriptの学習メモ。

今日は『確かな力が身につくJavaScript「超」入門』の第4章を読んでみます。

 

jsstudy.hatenablog.com

 

 

4.4 端数処理

(p.178)

「小数点第○位」で切り捨てるファンクションを作成します。

例では円周率を小数点第2位までで切り捨てて表示します。

 

足し算、引き算など四則演算は記号を使えばできますが、それ以外の計算には「Mathオブジェクト」というオブジェクトを使用します。

この実習で作成するファンクションでは、このMathオブジェクトのメソッドをいくつか使います。

 

端数処理 - Wikipedia

端数処理(はすうしょり)または丸め(まるめ)とは、与えられた数値を、ある一定の丸め幅の整数倍の数値に置き換えることである。

常用的には、10の累乗(…、100、10、1、0.1、0.01、…)が丸め幅とされることが多い。

 

  • 切り捨て
  • 切り上げ
  • 四捨五入

など

 

サンプルコード

以下の内容を「index.html」というファイル名で保存します。

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>4-04_math</title>
</head>
<body>
    <h1>小数点第◯位で切り捨てる</h1>
    <h2>四則演算以外の計算をする</h2>
    <p>円周率は<span><script>document.write(Math.PI);</script></span> です。</p>
    <p>ふつうに切り捨てると<span><script>document.write(Math.floor(Math.PI));</script></span> です。</p>
    <p>小数点第2位で切り捨てると<span id="output"></span>です。</p>
    <script>
        var point = function (num, digit) {
            var time = Math.pow(10, digit);
            return Math.floor(num * time) / time;
        }
        document.getElementById('output').textContent = point(Math.PI, 2);
    </script>
</body>
</html>

 

実行結果

上記のHTMLファイルをブラウザーで開きます。

 

f:id:jsstudy:20170510064410p:plain

 

切り捨ての桁数が指定できました。

 

Mathオブジェクト

JavaScriptであらかじめ用意されているMathオブジェクトには、様々なメソッドとプロパティーがあります。

 

developer.mozilla.org

 

Math は、数学的な定数と関数を提供するプロパティとメソッドを持つ、組み込みのオブジェクトです。

関数オブジェクトではありません。

 

Mathオブジェクトは初期化しないで使う

説明

他のグローバルオブジェクトと異なり、Math はコンストラクタではありません。

Math オブジェクトのすべてのプロパティとメソッドは、静的です。

円周率を表す定数πは、Math.PI として参照でき、正弦 (sine) 関数は、Math.sin(x) として呼び出すことができます (ここでの x は、メソッドの引数です)。

定数は、JavaScript における実数での完全精度で定義されています。

 

(p.183)

Mathオブジェクトには、計算に関する多くのメソッドと、数学的に意味のある定数(たとえば円周率など)があらかじめ代入されたプロパティが登録されています。

Mathオブジェクトのプロパティはすべて読み取り専用で、書き換えることはできません。

円周率が勝手に書き換えられるようなことがあってはいけないのです。

MathオブジェクトはDateオブジェクトと違って、使用するときに初期化しません。

つまり、次のように書く必要はありません。いや、書いてはいけません。

var math = new Math();

 

jsstudy.hatenablog.com

 

オブジェクトには初期化するものとしないものがある

オブジェクトの中には、Dateオブジェクトのように、使用するときにnewキーワードを使って「初期化」をするものがあります。

一方、4-4節で紹介するMathオブジェクトのやwindowオブジェクト、documentオブジェクトは初期化しません。

どうしてオブジェクトによって初期化したりしなかったりするのでしょうか?

実は、オブジェクトを初期化するかどうかには、次のような決まりがあります。

 

  • 複数のオブジェクトを作れるオブジェクトは初期化する
  • 複数のオブジェクトを作れないオブジェクトは初期化しない 

 

●Mathオブジェクトは「複数作れない」

一方、4-4節で紹介するMathオブジェクトはコピーを作ることができません。

Mathオブジェクトのプロパティはすべて読み取り専用で、書き換えることができないようになっていて、オブジェクトごとに独立のプロパティ値を持つ必要がありません。

そのため、Mathオブジェクトは元オブジェクトからコピーができず、複数のオブジェクトを作れないようになっているのです。

 

Mathオブジェクトの主なプロパティーとメソッド

プロパティー 説明
Math.PI 円周率。約3.14159
Math.SQRT1_2 1/2の平方根。約0.707
Math.SQRT2 2の平方根。約1.414

 

メソッド 説明
Math.abs(x) xの絶対値
Math.ceil(x) xの小数点以下を切り上げる
Math.floor(x) xの小数点以下を切り捨てる
Math.round(x) xの小数点以下を丸める(四捨五入)
Math.sin(x) xのサイン
Math.cos(x) xのコサイン
Math.tan(x) xのタンジェント
Math.sqrt(x) xの平方根
Math.pow(x,y) xのy乗
Math.max(a,b, ...) ()内のパラメーターa、b...のうち最大の数を返す
Math.min(a,b, ...) ()内のパラメーターa、b...のうち最小の数を返す
Math.random() 0以上1未満の乱数

 

小数点第◯位で切り捨てるアルゴリズム

(p.180)

書式:小数点以下を切り捨てる

Math.floor(数値)

 

Mathオブジェクトの切り捨てメソッドはfloorしかありません。

つまり、JavaScriptが用意している機能では、小数点以下を切り捨てることしかできないのです。

さてどうしましょう?

 

floorメソッドが小数点以下を切り捨てるなら、元の数字の小数点を、切り捨てたい位の手前まで動かせばよいことになります。

そこで、次の手順で計算します。

 

(1) 10を○回掛ける。○には「小数点以下第○位」の○が入る。たとえば○が「2」なら、10を2回掛ける、つまり10×10を計算する。もう少し数学的にいえば、10の○乗を計算する

(2) 元の数字に、(1)の計算結果を掛ける。これで小数点が移動する

(3) 小数点が移動した数字の、小数点以下を切り捨てる(つまり、floorメソッドを使う)

(4) 小数点以下を切り捨てた数字を、(1)の計算結果で割る。これで小数点が元の位置に戻る

 

例:「3.1415」を小数点第2位で切り捨てる計算方法

「3.1415」を小数点第2位で切り捨てると、「3.14」が求める答になります。

 

小数点以下をバッサリ切り捨てるMath.floor()をそのまま適用すると、

Math.floor(3.1415); → 「3」になってしまいます。

 

上記の方法を使って、まず先に小数点を移動させておきます。

小数点第2位2桁ずらす → 10の2乗(10×10=100)をかけると2桁ずれる

3.1415 * 100 = 314.15

 

これにMath.floor()を適用して、小数点以下を切り捨てると、

Math.floor(314.15); → 「314」になります。

 

2桁ずらしていた小数点を元に戻すために、10の2乗(=100)で割ります。

314 / 100 = 3.14

 

これで、欲しかった数字「3.14」が得られました。

単純な機能しかないMath.floor()でも、計算方法を工夫することで、小数点第2位で切り捨てる、という処理ができました。

 

まとめ

  • Mathオブジェクトは初期化しないで使う。
  • Mathオブジェクトに持たせているプロパティー(円周率などの定数)は変更できたらまずいので、最初からMathオブジェクトはコピーできない(複数のオブジェクトを作れない)ような仕組みにされてしまっている。
  • 計算方法を工夫することで、Mathオブジェクトの単純なメソッドも様々に活用できる

 

Mathオブジェクトを活用して、計算をスムーズにできるようになりたいです。