関数・メソッド

【JavaScript】立方根(∛)を組みこみ関数または自力で計算する方法

更新日:2023/07/12

JavaScriptで立方根を求める方法をお伝えします。
立方根とは平方根の3乗バージョンです。
(雑な解説すぎる…)

 

組み込み関数を使用する

JavaScriptは組み込みオブジェクトMathに、立方根を計算するcbrt()メソッドが定義されています。
メソッド名が分かりにくいですね。
立方根は英語では cube rootなので、ここから文字を拾ってきたようです。

Math.cbrt()は、次のように定義されています。

Math.cbrt()の構文

Math.cbrt( x )

xは、isNaN(x)でfalseを返す値、かつ0以上です。

isNaN(x)でfalseを返す値
100 や 200 などの数値
"100" や "200" などの数値文字列
true ⇒ 1、false ⇒ 0
null ⇒ 0
[Symbol.toPrimitive]を適切に実装したオブジェクト

整数の範囲では平方根は+値と-値の値を持ちますが、立方根は一つです。

次のコードは、Math.cbrt()の使用例です。

使用例

console.log( Math.cbrt( 100 ) );   // 結果: 4.641588833612779
console.log( Math.cbrt( "100" ));// 結果: 4.641588833612779
console.log( Math.cbrt( null ) ); // 結果: 0

const obj = {
    value:100,
    [ Symbol.toPrimitive ](hint){
        switch(hint){
            case "string": return this.value.toString();
            case "number": 
            case "default": 
            default:  return this.value;
        }
    }
};
console.log( Math.cbrt( obj ) );// 結果: 4.641588833612779

3乗して元の値が得られるか確認してみます。

console.log( 4.641588833612779 * 4.641588833612779 * 4.641588833612779 );
  // 結果: 100.00000000000003

元の値と同じになりました。
少しズレてる?

JavaScriptの数値データは浮動小数点という形式で扱われます。
この形式は小数点の扱いが少し苦手で、計算結果が少しズレることがあります。
そもそも 3分の1 (0.33333...)などの割り切れない値も無理やり計算されるので、これくらいのズレは許容範囲だったりしますね。

 

べき乗を使用する

べき乗で計算する方法もあります。

aは、aの3分の1乗と同値です。
そのためJavaScriptのべき乗演算子を使って計算できます。

べき乗による立方根演算

√a = a ** (1/3)

この方法を使って、10から30までの立方根を求めてみます。

const c = 1/3;
for( i = 10 ; i <= 30 ; i ++ ) {
    const r1 = i ** c;
    const r2 = Math.cbrt(i);
    console.log( i,r1 , r2 , r1 - r2 );
}

Math.cbrt()の結果と比較しています。

結果は次のようになります。

10 2.154434690031884 2.154434690031884 0
11 2.2239800905693152 2.2239800905693157 -4.440892098500626e-16
12 2.2894284851066637 2.2894284851066637 0
13 2.3513346877207573 2.3513346877207573 0
14 2.4101422641752297 2.41014226417523 -4.440892098500626e-16
15 2.46621207433047 2.46621207433047 0
16 2.5198420997897464 2.5198420997897464 0
17 2.571281590658235 2.571281590658235 0
18 2.6207413942088964 2.6207413942088964 0
19 2.668401648721945 2.668401648721945 0
20 2.7144176165949063 2.7144176165949063 0
21 2.7589241763811203 2.7589241763811208 -4.440892098500626e-16
22 2.802039330655387 2.8020393306553872 -4.440892098500626e-16
23 2.8438669798515654 2.8438669798515654 0
24 2.8844991406148166 2.8844991406148166 0
25 2.924017738212866 2.924017738212866 0
26 2.9624960684073702 2.9624960684073707 -4.440892098500626e-16
27 3 3 0
28 3.0365889718756622 3.0365889718756627 -4.440892098500626e-16
29 3.072316825685847 3.0723168256858475 -4.440892098500626e-16
30 3.1072325059538586 3.1072325059538586 0

微妙にズレました。
Math.cbrt()とべき乗での計算は、内部的なアルゴリズムが異なるようですね。

 

自力で計算する

平方根の記事ニュートン法を紹介したので、立方根でもやってみます。

ニュートン法は次のような公式でした。

xn+1 = xn - f(xn) / f´(xn)

求めたい立方根を、v とします。

f(x)f´(x) は、次のようになります。

f(x) = x3 - v
f´(x) = 3x2

公式に当てはめます。

xn+1 = xn - (xn3 - v) / 3xn2
  = xn - xn / 3 + v / 3xn2

3乗を避ける方向で変形してみました。

これを使ってコードを作成してみます。

const cube_root = ((threshold)=>{
    const th = threshold; // 閾値
    return value =>{
        let before_x,x= value;
        do{
            before_x = x;
            x = before_x - before_x / 3 +  value/(3*(before_x**2));
        }while( Math.abs( before_x - x ) > th );
        return Math.abs( x );
    };
})(0.00000001);

この関数を使って、10から30までの立方根を求めてみます。

for( i = 10 ; i <= 30 ; i ++ ) {
    const r1 = cube_root(i);
    const r2 = Math.cbrt(i);
    console.log( i,r1 , r2 , r1 - r2 );
}

次のような結果になりました。

10 2.154434690031884 2.154434690031884 0
11 2.2239800905693152 2.2239800905693157 -4.440892098500626e-16
12 2.289428485106664 2.2894284851066637 4.440892098500626e-16
13 2.3513346877207573 2.3513346877207573 0
14 2.41014226417523 2.41014226417523 0
15 2.46621207433047 2.46621207433047 0
16 2.5198420997897464 2.5198420997897464 0
17 2.5712815906582356 2.571281590658235 4.440892098500626e-16
18 2.6207413942088964 2.6207413942088964 0
19 2.668401648721945 2.668401648721945 0
20 2.7144176165949063 2.7144176165949063 0
21 2.7589241763811208 2.7589241763811208 0
22 2.8020393306553872 2.8020393306553872 0
23 2.8438669798515654 2.8438669798515654 0
24 2.8844991406148166 2.8844991406148166 0
25 2.924017738212866 2.924017738212866 0
26 2.9624960684073707 2.9624960684073707 0
27 3 3 0
28 3.0365889718756622 3.0365889718756627 -4.440892098500626e-16
29 3.072316825685847 3.0723168256858475 -4.440892098500626e-16
30 3.107232505953859 3.1072325059538586 4.440892098500626e-16

ほぼ、同じ結果ですね。

更新日:2023/07/12

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。