■ No.4 (2001.11.07) … 簡単なプログラミング II and 2次式に現れる素数

● 名前のついてない関数(純関数) … 引数が#1, #2,... と書かれる計算 &
→ 一回しか使わないような関数をわざわざ定義しなくても使えるようにした Syntax Sugar の一つ.
→ 単純な関数に対しては積極的に使った方がプログラムが読みやすくなる.
→ 実行速度が速くなる,というメリットもあるらしい.
→ 最後に & をつけるのを忘れずに.
→ #1 は # と省略して書いてもよい.

次の例のように使う.

    In[1]:= a = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

    In[2]:= a // N[Sin[#]] &         ← Map[N[Sin[#]]&, a] とこの場合は同じ.
    Out[2]= {0.841471, -0.756802, 0.412118, -0.287903, -0.132352, 
               -0.991779, -0.953753, 0.920026, -0.629888, -0.506366}


    In[3]:= NS[x_] := N[Sin[x]]      ← 純関数を使わない場合は,こうして新たに関数を定義してから,
    In[4]:= a // NS                  ← 使うということになる.
    Out[4]= {0.841471, -0.756802, 0.412118, -0.287903, -0.132352, 
               -0.991779, -0.953753, 0.920026, -0.629888, -0.506366}  ← もちろん Out[2] と同じになる.
    

2次式にあらわれる素数

■ 双平方
2つの1以上の整数の平方(= 二乗)の和である整数を双平方であるという.

では,双平方な数について何かわかることはないか調べてみよう.

まずは一番簡単な,12 + m2 (m=1,2,... ) という形のものから調べてみよう.

    In[1]:= Ds[n_,m_] := n^2 + m^2

    In[2]:= a = Table[Ds[1, n], {n, 1, 20}]
    Out[2]= {2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170, 197, 226, 257, 290, 325, 362, 401}
    

数学の世界では, 整数についてまずチェックすべき性質は素数との関係である ということになっているので(^-^;),

● 素数かどうかの判定 … PrimeQ[数]

を使って素数なものを抜き出してみると次のようになる.

    In[3]:= Select[a, PrimeQ]
    Out[3]= {2, 5, 17, 37, 101, 197, 257, 401}
    

さらに数学の世界では, 整数について素数性の次にチェックすべき性質は「何か整数で割ってみたときの振る舞い」 ということにもなっているので, 12 + m2 を 2,3,4,5,6,7,8,... で割ってみて様子を見てみよう.

● 整数の割り算の答え … Quotient[a, b] → a ÷ b = c 余り d という時の c である

という命令と以前紹介した Mod を使って,

    In[4]:= QM[x_, n_] := {x, Quotient[x,n], Mod[x,n]}

    In[5]:= QM[21,5]
    Out[5]= {21,4,1}      ← 要するに,21 ÷ 5 = 4 余り 1 の 21と右辺 が出てくる.
    

という関数を定義しておいて,2 で割った場合,3 で割った場合 … とやってみよう.
素数であるところにはそう記してある.

    In[6]:= Map[QM[#, 2]& , a] //TableForm  ← 2 で割った場合. 純関数を用いていることに注意.
    Out[6]//TableForm=
        2     1     0       ← 素数  
        5     2     1       ← 素数
        10    5     0
        17    8     1       ← 素数
        26    13    0
        37    18    1       ← 素数
        50    25    0
        65    32    1
        82    41    0
        101   50    1       ← 素数
        122   61    0
        145   72    1
        170   85    0
        197   98    1       ← 素数
        226   113   0
        257   128   1       ← 素数
        290   145   0
        325   162   1
        362   181   0
        401   200   1       ← 素数

    In[7]:= Map[QM[#, 3]& , a] //TableForm  ← 3 で割った場合
    Out[7]//TableForm=
        2     0     2       ← 素数
        5     1     2       ← 素数
        10    3     1
        17    5     2       ← 素数
        26    8     2
        37    12    1       ← 素数
        50    16    2
        65    21    2
        82    27    1
        101   33    2       ← 素数
        122   40    2
        145   48    1
        170   56    2
        197   65    2       ← 素数
        226   75    1
        257   85    2       ← 素数
        290   96    2
        325   108   1
        362   120   2
        401   133   2       ← 素数

    In[8]:= Map[QM[#, 4]& , a] //TableForm  ← 4 で割った場合
    Out[8]//TableForm=
        2     0     2       ← 素数
        5     1     1       ← 素数
        10    2     2
        17    4     1       ← 素数
        26    6     2
        37    9     1       ← 素数
        50    12    2
        65    16    1
        82    20    2
        101   25    1       ← 素数
        122   30    2
        145   36    1
        170   42    2
        197   49    1       ← 素数
        226   56    2
        257   64    1       ← 素数
        290   72    2
        325   81    1
        362   90    2
        401   100   1       ← 素数

    In[9]:= Map[QM[#, 5]& , a] //TableForm  ← 5 で割った場合
    Out[9]//TableForm=
        2     0    2       ← 素数
        5     1    0       ← 素数
        10    2    0
        17    3    2       ← 素数
        26    5    1
        37    7    2       ← 素数
        50    10   0
        65    13   0
        82    16   2
        101   20   1       ← 素数
        122   24   2
        145   29   0
        170   34   0
        197   39   2       ← 素数
        226   45   1
        257   51   2       ← 素数
        290   58   0
        325   65   0
        362   72   2
        401   80   1       ← 素数
    

となり,次のような仮説をたてると正否はどうなるかというと…

■ 仮説1 双平方数は 2 で割って余り 1 ならば素数 ⇒ 正しくない
■ 仮説2 双平方数は 素数ならば 2 で割って余り 1 ⇒ 2 を除いて正しい?

■ 仮説3 双平方数は 3 で割って余り ほげほげ ならば素数 ⇒ 正しくない
■ 仮説4 双平方数は 素数ならば 3 で割って余り ほげほげ ⇒ 正しくない

■ 仮説5 双平方数は 4 で割って余り ほげほげ ならば素数 ⇒ 正しくない
■ 仮説6 双平方数は 素数ならば 4 で割って余り 1 ⇒ 2 を除いて正しい?

■ 仮説7 双平方数は 5 で割って余り ほげほげ ならば素数 ⇒ 正しくない
■ 仮説8 双平方数は 素数ならば 5 で割って余り ほげほげ ⇒ 正しくない

となる(ただし,ここでは双平方数は 12 + m2 の形だけを考えている).

□ レポート課題 1 同様に,12+m2 の形の双平方数を 6,7,8 で割ったときの仮説を考え,その正否を調べよ.

仮説2 は,2以外は素数は奇数,ということから「当たり前」なのでいいとして(つまり,双平方数かどうかに関係ない), 仮説6 は「新しい発見」である.
そこで,仮説6をきちんと書いてみよう.

■ 仮説9 双平方数かつ素数は 4 で割って 1余る.

□ レポート課題 2 仮説9 が一般の双平方数(n2+m2 の形)に対して成り立つかどうか Mathematica で調べよ.

さて,仮説9 の形の「逆」の形の仮説は提案できないか調べてみよう.

● 論理演算 … !(Not), &&(And), ||(Or)
→ !式 は式の否定,式1 && 式2 は 式1と式2の論理積,式1 || 式2 は論理和を返す.
T で True, F で False を表すとして,論理演算を表で表すと次のようになる.
論理否定 !(Not)
!式
T F
F T

論理積 &&(And)
式2 \ 式1 T F
T T F
F F F

論理和 ||(Or)
式2 \ 式1 T F
T T T
F T F

与えられた整数が双平方数かどうかチェックする関数 DsQ を上の論理演算を使って最初に以下のように作っておいて,

    In[10]:= DsQ[n_] := Module[{Answer, i, R},
               i = 1;
               Answer = False;
               While[(!Answer) && (i <= Sqrt[Quotient[n, 2]]), 
                 R = Sqrt[n - i^2];
                 Answer = IntegerQ[R] && Positive[R];
                 i++;
                 ];
               Return[Answer]
               ]

    In[11]:= Table[{n, DsQ[n]}, {n, 1, 20}] // TableForm   ← 20 まで DsQ が正しく動くかどうかチェック.
    Out[11]//TableForm=
        1    False
        2    True
        3    False
        4    False
        5    True
        6    False
        7    False
        8    True
        9    False
        10   True
        11   False
        12   False
        13   True
        14   False
        15   False
        16   False
        17   True
        18   True
        19   False
        20   True
    

まず,4 で割って 1 余る普通の整数は双平方かどうかみてみる.

    In[12]:= b = Table[4*n+1, {n,0,19}]  ← 4 で割って 1 余る数を小さい順に20個作っている
    Out[12]= {1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77}

    In[13]:= Map[DsQ, b] 
    Out[13]= {False, True, False, True, True, False, True, True, 
                False, True, True, True, False, True, False, True, True, False, True, False}
    

… どうもそうとは限らないようだ.
では,4 で割って 1 余る素数は双平方かどうかを次にみてみよう.

    In[14]:= c = Select[b, PrimeQ]  ← 4で割って1余る数の中で素数なものを抜き出している
    Out[14]= {5, 13, 17, 29, 37, 41, 53, 61, 73}

    In[15]:= Map[DsQ, c]
    Out[15]= {True, True, True, True, True, True, True, True, True}
    

正しいように見える.よって,以下の仮説が提案できるだろう.

■ 仮説10 4で割って1余る素数は双平方である.

□ レポート課題 3 p に対して p = a2 + b2 となる a, b (1以上の整数)の組を求める関数を Mathematica で作り, 100個程度の 4 で割って 1余る素数 p に対して計算してみよ.

この仮説と仮説9,さらに 2 が素数かつ双平方であることを併せて考えると,結局次の仮説にたどり着く.

■ 仮説11 (フェルマー-オイラーの定理) 素数 p が4で割って1余る or p=2 ⇔ 素数 p は双平方.

□ レポート課題 4 仮説 11 を数学的に証明せよ.

→知識がないと難しいと思われる… と思ったが,
→数学セミナー(日本評論社) 2000.09 の p.3--5 に通常の証明とは異なる非常に分かりやすい証明が載っている. 数学を知らなくても理解できる. この証明を思いつくのはほとんど不可能だが…


>> 目次