본문 바로가기

카테고리 없음

(정수론/파이썬) 천 만개씩 소수를 구해 피클 파일로 저장하기

C언어에 비해 한참 느리긴 하지만 파이썬으로 작업하면 쉽고 편하게 할 수 있다.

소수 1천만개 구하는 데 1시간 이상 걸리니까 며칠 돌려 놓으면 몇 억개 구할 수 있지 않을까 희망해본다.

소수를 구해 리스트에 넣은 다음, 일정한 갯수(여기서는 1천만개)에 달하면 피클 파일로 저장한다.

매번 다른 파일명으로 차례로 저장하고, 무한 루프를 돈다. 뒤로 갈수록 시간이 점점 더 걸린다.

 

2억개 정도 마련하면 이 피클 파일들을 하나로 통합해서 관리하면 한결 수월할 것이다.

이 파이썬 코드를 실행하는 폴더 안에 data/라는 폴더를 미리 만들어두어야 한다. 생성되는 피클 파일이 여러 개인지라...

import math
import pickle
import os.path

def is_prime(num):
    if num <= 1:
        return False
    if num == 2: return True
    if num ==  3: return True
    if num % 2 == 0:
        return False
    root_val = int(math.sqrt(num)) + 1
    for i in range(3, root_val, 2):
        if num % i == 0:
            return False
    return True


def get_divisors2(from_num, until_num):  # 양쪽 포함
    num = from_num
    primes = []
    if num == 2:
        print(num)
        primes.append(num)
        num += 1  # 3
    if num == 3:
        print(num)
        primes.append(num)
        num += 2
    if num % 2 == 0:  # 짝수라면, 홀수부터 시작
        num += 1
    u_num = until_num + 1
    for x in range(num, u_num, 2): # 최소 5부터 시작
        root_val = int(math.sqrt(x)) + 1
        flag = True  # 일단 True로 설정
        for i in range(3, root_val, 2):
            if x % i == 0:  # 합성수라면
                flag = False
                break
        if flag == True:
            primes.append(x)
            print(x)
    return primes
 

def get_divisors(from_num, until_num):  # 양쪽 포함
    num = from_num
    primes = []
    if num == 2:
        print(num)
        primes.append(num)
        num += 1  # 3
    if num % 2 == 0:  # 짝수라면, 홀수부터 시작
        num += 1
    u_num = until_num + 1
    for x in range(num, u_num, 2): # x는 5부터 시작
        if is_prime(x):
            primes.append(x)
            print(x)
    return primes


def get_divisors3(from_num, howmany):  # 양쪽 포함
    num = from_num
    primes = []
    count = 0
    if num == 2:
        #print(num)
        primes.append(num)
        num += 1  # 3
        count += 1
    #if num == 3:
     #   print(num)
     #   primes.append(num)
     #   count += 1
    if num % 2 == 0:  # 짝수라면, 홀수부터 시작
        num += 1      # 4라면 5
    
    while count < howmany:
        if is_prime(num):
            primes.append(num)
            count += 1
            #print(num)
        num += 2
    return primes


#UINT_MAX = 4294967295
#ULONG_MAX = 18,446,744,073,709,551,615
#MAX_COUNT = 100000000  # 1억개
filename_base = "data/primes_"

MAX_COUNT = 10000000  # 천만개, 한번에 구할 소수 갯수
start_num  = 1
count = 0   # 반복문 실행 회수: 생성되는 pkl 파일 갯수

while True:
  primes = get_divisors3(start_num+1, MAX_COUNT) 
  count += 1
  pkl_filename = filename_base + str(count) + ".pkl" # "primes_1.pkl"
  if os.path.isfile(pkl_filename):
    print(f"{pkl_filename}이 이미 있습니다.")

  with open(pkl_filename, "wb") as pf:
    pickle.dump(primes, pf)

  length = len(primes)
  print(f"{length} 개의 데이터를 피클로 저장했습니다.")
  print(primes[:10])  # 첫 10개
  print(primes[length-10:])  # 마지막 10개

  start_num = primes[-1]  # 마지막 소수 + 1에서 다시 검사 시작