2014年08月04日

「Y=X以下の素数の数」となる関数は素数計数関数といいます。
X以下の素数の数
primeplot
素数計数関数は素数定理にて近似関数が出ています。
X以下の素数の数、Y=X/Log(X)、Y=Li(X)
liplot


で、タイトルなんですが「X以下の素数の数」が近似関数が得られるようなグラフになる、ということは適当に「X以下の数の因数の数の合計」や「素因数の数の合計」もなにか秩序だったものになるかもしれない、と考えC#でプログラムを書きグラフを描画するライブラリを借りてグラフにしてみた次第です。無駄に時間がかかりましたが楽しかったのでいいとして、結果がこちら。
X以下の因数の数、素因数の数
 factorplot

2以上10000未満のX以下の数の因数の数の合計、素因数の合計
factorplot10000

近似関数はあるのでしょうか?気になりますね。

ビルドした(だけの)上3つのグラフを見れるソフトをおいておきます。(クリックでダウンロード)
charWPF



計算式(C#)
素数の生成は小さいほうから素数の倍数を合成数と認定していく方法ととっています。
素因数分解と上記の素数生成を組み合わせていい感じのアルゴリズムが出来ました。
オーダーX以下の要素の合計はC#の便利な機能Linqを使い、<配列>.Take(X+1).Sum()で簡単に記述ができます。
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MathematicsTest
{
    public class Program
    {

        /// <summary>
        /// 2以上max以下の素因数の数の配列を返す
        /// </summary>
        /// <param name="max">2以上</param>
        /// <returns></returns>
        public static int[] NumbersOfPrimeFactor(int max)
        {
            max++;

            var primeData = new int[max];
            for (int i = 2; i < max; i++)
            {
                if (primeData[i] == 0)
                    for (int j = i; j < max; j += i)
                    {
                        for (int _j = j; _j % i == 0; _j /= i) primeData[j]++;
                    }
            }

            return primeData;
        }


        /// <summary>
        /// 2以上max以下の因数の数の配列を返す
        /// </summary>
        /// <param name="max">2以上</param>
        /// <returns></returns>
        public static int[] NumbersOfFactor(int max)
        {
            max++;

            var primeData = new int[max];
            for (int i = 2; i < max; i++) primeData[i] = 1;
            for (int i = 2; i < max; i++)
            {
                if (primeData[i] == 1)
                    for (int j = i+i; j < max; j += i)
                    {
                        int n = 1;
                        for (int _j = j; _j % i == 0; _j /= i) n++;
                        primeData[j] *= n;
                    }
            }

            return primeData;
        }

        public static bool[] GetIsPrime(int max)
        {
            max++;
            bool[] isPrime = new bool[max];
            for (int i = 2; i < max; i++) isPrime[i] = true;
            for (int i = 2; i < max; i++)
            {
                if (isPrime[i] == true)
                {
                    for (int j = i + i; j < max; j += i)
                        isPrime[j] = false;
                }
            }

            return isPrime;
        }

        public static int[] Primes(int max)
        {
            return PrimeEnum(max).ToArray();
        }

        //max以下の素数を小さい方から順に返す
       public  static IEnumerable<int> PrimeEnum(int max)
        {
            max++;
            bool[] isNoPrime = new bool[max];
            for (int i = 2; i < max; i++)
            {
                if (isNoPrime[i] == false)
                {
                    yield return i;
                    for (int j = i + i; j < max; j += i)
                        isNoPrime[j] = true;
                }
            }
        }
    }
}


近似関数
X以下の数のすべての因数の数の合計に近似値を出せる関数として「Y=X*ln(X)」を見つけました。
ぴったりですね。
totalfactorxln30
totalfactorxln50000

X以下の素数の数が「Y=X/ln(X)」なのだとすると、X以下の素数の数掛けるX以下の因数の数はX^2・・・?
わりと興味深いですね。素数と関連しそうな「素因数の数」になにかが見つかるかと思ったら、計算が少し上の、「因数の数」に見つかってしまいました。因数の数の関数はだめもとだったのでしたがよかったです。
あれ?よく見るとだんだん差が広がっているような・・・?近似関数じゃない・・・?

上記の関数のグラフでコンパイルしたのをおいておきます。


おわり

OxyPlotというライブラリ様を今回使ってみましたが、操作性、グラフィック、拡張性、どれも素晴らしかったです。
参考リンク
C#でグラフを描く OxyPlotのFunctionSeriesによる方法 - whoopsidaisies's diary


なんか無駄に洗練された記事になってるのはブランク脳内研鑽の成果です。 

トラックバックURL

この記事へのコメント

1. Posted by FXをしよう!   2014年10月23日 11:50
<SPAM投稿のため削除>
いやぁ・・・初スパムですよ(by管理人)

コメントする

名前
 
  絵文字