dc(1)를 사용하여 소수 생성

14735 단어 shelldc소수tech
저는 저번 보도 이후 dc에 빠진 귤입니다. 이번에는 dc와 셸으로 소수를 생성했습니다.

펠트 소정리


페마의 작은 정리는 소수의 성질 중의 하나를 나타내는 정리 중의 하나다.
이 정리는 소수 p와 p의 배수가 아닌 적당한 정수 a에 대해 아래의 공식을 세운다.
a^{p-1}\equiv 1\hspace{-1ex}\mod p
이 정리를 이용한 대구는 페마 테스트가 있는데 이것은 n과 상호위소의 a가 하식을 만족시키면 n이 합성수임을 나타낸다.
a^{n-1}\not\equiv 1\hspace{-1ex}\mod n

방침.


소수:
  • 적당히 생각한 수량을 n으로 설정하고, 이미 알고 있는 소수를 a로 설정하여 필마 테스트를 실시한다.
  • 페르마 테스트 결과 n이 합성수가 아니라는 것을 확인하면 a를 다른 소수로 바꾸고 다시 1.로 돌아가기
  • 합성수로 판단되면 n.
  • 지칠 때까지.그리고
  • 보아하니 n은 소수일 것 같다

    dc의 사용법


    바로 dc가 무한정밀도 컴퓨터를 표방하고 있기 때문에 큰 비트도 계산하기 어렵지 않을 뿐만 아니라 GNU판의 dc는 멱여수의 산수를 갖추고 있기 때문에 첫 번째 공식[1]을 간단하게 계산할 수 있다.
    예를 들어 n=32529, a=11이 페마 테스트를 실시하면 다음과 같다. 결과는 1이 아니라 이번 n은 소수가 아닌 것 같다.
    $ echo "11 32529d1-r|p" | dc
    22108
    

    마음대로 수를 세어 보아라


    개수를 적당히 생각하기 위해 이용/dev/urandom. 적당하면 되기 때문에 사용하지 말아야 한다/dev/random./dev/urandom에서 읽은 것은 이진 데이터지만 이진 데이터를 직접 처리하는 것은 매우 힘들기 때문에 텍스트로 변환하고임의의 16진수는 64바이트를 출력할 수 있습니다. 여러 가지 옵션이 있지만, 각각 오프셋 -An 을 표시하지 않고, 64바이트 -N64 만 표시하고, 8개의 바이트로 구분된 16진수 표시 -tx8 를 지정합니다.
    $ od -An -N64 -tx8 /dev/urandom
     6cbff7a8b328a334 cd02607bfca7f24a
     87222740f2b9496d 6e3ace39a3cb82df
     7a6342f2bb52161b 0f468f29f9f3ef56
     b31f49269323dc29 b9d63f2ae7ddb6df
    
    단, 이렇게 하면 64바이트의 적정 수량보다 8바이트의 적정 수량이 8개가 된다. 따라서 sed(1)를 이용하여 공백 문자를 제거한다. 고려한 후 dc에 건네주고 대문자로 변환한다. 아래 명령은 GNU 버전의sed에서 이동한다.이외에-z 옵션에 화가 날 수 있습니다.
    이번에 나는 정말 적당한 숫자를 생각해 냈다.

    알려진 소수 준비


    이 구역은 이미 없어졌다.이곳의 지령을 집행해도 당시의 목적을 실현할 수 없다.(2021-04-25)
    여기 있던 것들
    필마 테스트에 사용할 a의 적정 소수를 준비해야 한다. 의심스러운 소수지만, 여기. 과거 자신이 준비한 소수 일람표가 있기 때문에 그.prime.txt의 이름으로 함께 보관해야 한다.
    결과는 필요 없어요.
    $ od -An -N64 -tx8 /dev/urandom | \
    > sed -ze 's/\(.*\)/\U\1/g; s/[[:space:]]//g'
    2F841CA1352FACBCEE4481E502AE1E8286EC562496741EE9B56ECB0085D092733B65E2F685E120F97603CA247A556E39350F64CC55D1B4420EE09FC1CDDB6CA3
    

    일단 써볼게요.


    그리고 아래처럼 적당한 각본을 쓰세요.
    prime.sh
    $ for i in `seq 0 9`; do
    > curl https://www.kusaremkn.com/prime/$i.txt >>prime.txt;
    > done
    

    실행하다


    적당히 변경randGen()한od의 옵션-N64, 아래 명령을 집행한 결과의 개요.
    #!/bin/sh
    
    # フェルマの小定理
    # fermat(a, n)
    fermat() {
    	if [ $# -ne 2 ]; then
    		return 1
    	fi
    	if [ `echo "[1sr]sP0sr16i$1 $2d1-r|1=Plrp" | dc` -eq 0 ]; then
    		return 1
    	fi
    	return 0
    }
    
    # 素数 (っぽい) かどうか調べる
    # isPrime(n)
    isPrime() {
    	if [ $# -ne 1 ]; then 
    		return 1
    	fi
    	cat prime.txt | while read line; do
    		printf "."
    		if ! fermat $line $1; then
    			printf "#"
    			return 1
    		fi
    	done
    }
    
    # 適当な数を思いつく
    # randGen()
    randGen() {
    	od -An -N64 -tx8 /dev/urandom | \
    		sed -ze 's/\(.*\)/\U\1/g; s/[[:space:]]//g'
    }
    
    RandNum=`randGen`
    while ! isPrime $RandNum; do
    	RandNum=`randGen`
    done
    echo
    echo "`echo "16i${RandNum}p" | dc` may be prime number."
    
    옵션
    생성소수
    실행 시간-N4 (32bit)
    2732855357(소수)
    1m26.050s-N8 (64bit)
    130970607\123597119(소수)
    1m50.535s-N16 (128bit)
    1915996383\212058763\191072604\200883991(소수)
    3m42.332s-N32 (256bit)
    1103595478\49974420\6585173347\4602803964\1301281974\44387502812\96753800\044961237(소수)
    21m45.643s-N64 (512bit)
    ¯\_(ts)/¯
    NaN
    아, 너무 늦었어. 소수가 아닌 숫자가 a=2의 페마 테스트에서 떨어졌어. 소요된 시간은 거의 소수에서 소수가 정말 소수인지 아닌지를 판단하는 데 걸렸어.그것을 19도 정도 짜서 다시 실험하자. 취미용 소수이기 때문에 의소수를 섞어도 문제없다.
    prime2.sh
    $ time sh prime.sh
    
    개정의 실행 결과는 다음과 같습니다.
    옵션
    생성소수
    실행 시간-N4 (32bit)
    3085616531(소수)
    0m0.021s-N8 (64bit)
    1476409253\5285870949(소수)
    0m0.033s-N16 (128bit)
    2285957700\89160096975\99988705\82580889(소수)
    0m1.313s-N32 (256bit)
    410798460\1097619771\177969692954\2846983472\4855398896\52097038\9898828337\8274057(소수)
    0m0.570s-N64 (512bit)
    9533664173\941981379\099845783\6154684221\2583977960\12436755\1969554340\29523495\86744972\5200953556\5464412058\3392107305\1010090813\9778012640\5727(소수)
    0m14.179s-N128 (1024bit)
    242494182121212121212121212121212121212121212121212121212121212121212121212121212121212121838348323237125857575757575757575757575757575757575757575757575715151515151515151521212121212123555557572727272727272727272727272727272727272727272727272727272721212121212121212121212121212121212121212121212121212121838383838383838383838383834848484848484848484848484848486464646464646464646464646464646464646464929292929292121212\23232363696969696060606060605062525252525273737373737373737373737373737373737330\6387476759\6649858689\3196569838\4595940637\2816223742\75613597(분별불가)
    2m5.427s

    총결산


    페르마의 작은 정리를 이용하면 50줄 미만의 프로그램에서 150자리 이상의 소수와 300자리 정도의 소수를 생성할 수 있다. 이 스크립트는 소수를 토하지 않지만, 손에는 소수를 얻지 못한다.
    소수 판정은 Worlfram Alpha를 사용했지만 150자리 이상의 숫자 인수를 분해할 수 있다는 것은 놀랍다. 또한 마지막 300자리 이상의 숫자가 소수인지 아닌지는 판별할 수 없다. 인수 분해를 할 수 있는 맹장이 있다면 이 시간을 다른 유용한 일에 사용해 보자.

    보충(03-21)


    이 글의 제목 dc(1)를 사용하여 소수를 생성하는 것이 도대체 타당한지...dc광은 소수의 판정...?
    이런 것들은 물론이고 이미 2048bit의 소수가 있다.442s. 랜덤으로 기분이 좋으면 현실 시간에 커다란 소수를 생성할 수 있다.
    --- prime.sh	2021-03-21 01:46:19.726158589 +0900
    +++ prime2.sh	2021-03-21 01:55:52.887732224 +0900
    @@ -18,7 +18,7 @@
     	if [ $# -ne 1 ]; then 
     		return 1
     	fi
    -	cat prime.txt | while read line; do
    +	for line in 2 3 5 7 11 13 17 19; do
     		printf "."
     		if ! fermat $line $1; then
     			printf "#"
    
    각주
    GNU 버전의 dc가 아니라면 위키백과dc이 절 코드를 읽어 주십시오. ↩︎
  • 좋은 웹페이지 즐겨찾기