ある数の全約数を求める方法&JavaScriptコード例

JavaScriptで次のことがしたい。

  • ある数、例えば 18 がある
  • その全ての約数を求めたい
  • 例えば 1,2,3,6,9,18 みたいに…

それにはいくつか手順が必要です。

ググっても中々答えが出てこないので、
自分でロジック/コードを考えてみました。

JavaScriptに限らず汎用的な手法です。

1.初めに数を素因数分解する

全約数を求めるには下準備が必要です。

それが対象の数を素因数分解すること

具体的には次のようなコードです。

▼ このようなコードを書いた

▼ いくつかの数を素因数分解する例

このような関数を作成しました。

上記の例で説明するなら、12を素因数分解すると 2^2*3^1  とあらわせるので [{count: 2, factor: 2},{count: 1, factor: 3}]  のような素因数・その指数のペア配列が返ってきます。

ちなみに上記はかなり簡素なアルゴリズムです。

▼ 速度を求めるならosa_k法など色々ある

https://pisuke-code.com/js-factorise-number-by-osa-k/

ひとまず素因数分解さえできればOK。

こうすると約数が求めやすいです。

2.全ての約数を素因数から求める

そしたら全ての約数を求めてみます。

本当はあまり良くないけど、
再帰を使うと超簡単に求めること可能です。

▼ 次のようなコードを書いた

このような関数で全約数がゲットできます。

問題なのは再帰的(recursively)なロジックであることです。一見スマートに見えるけど、実は再帰ってパフォーマンス的に最悪なですよね(-_-;)

詳しくは次記事でも書きました。

▼ 再帰なしでフィボナッチ数を求める

もしパフォーマンスを向上させたいなら…

再帰を使わないロジックに変更してください。

3.色々な数の全約数を求めてみた

上記の関数を使った結果がこれです。

▼ 適当な数で全約数を求めた

という感じで全ての約数が求められました。

実用的な範囲はMAX_SAFE_INTEGERまで

上記コードには実用的範囲の制限があります、

目安としては Number.MAX_SAFE_INTEGER  まで

▼ Number.MAX_SAFE_INTEGERの概要

Number.MAX_SAFE_INTEGER 定数は、JavaScript における安全な整数の最大値 (2^53-1) を表します。もっと大きな整数には、 BigInt を使用することを検討してください。

引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

2^53-1 = 9007199254740991

ここまでが実用的な範囲です。

それ以上でも期待通りに動くこともありますが、安全ではないので素因数分解できる保証はありません。エラーは出ないけど答えは間違っています。

その点に注意してください。

巨大数にも対応したいならBigIntを使う

上記の説明にあるように、

巨大数は BigInt  で扱えます。

▼ JavaScriotでのBigInt型

BigInt 値は、単に BigInt と呼ばれることもありますが、 bigint プリミティブです。整数リテラルの末尾に n を追加するか、 BigInt() コンストラクターを呼び出し、整数値または文字列値を与えることで生成することができます (ただし new 演算子なしで)。

引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/BigInt

ここまでのコードも BigInt  に置換可能。

興味のある人は試してみてください。

巨大数では素因数分解の速度も重要

もし巨大数のすべての約数を求めたいなら…

素因数分解の速度がとても重要です。

  • 巨大数は素因数分解に時間がかかる
  • どんなアルゴリズムを使うかが重要
  • メモリ使用量にも注意しないといけない

素因数分解は1つの分野になってます。

知ってる人は多いと思いますが、素因数分解は桁数が多いほど難しいです。そして300桁のような桁数になると現実的な時間で計算できません。それを応用したのがRSA暗号ですね。

巨大数の約数を求めるのは不可能かも
でも50桁程度なら頑張れば求められます。

ってことでJavaScriptで全約数の求め方でした。