큰 정수의 계산법
큰 정수의 덧셈
기본 내용
-
리스트를 이용하여 각 자리수(digit)를 하나의 원소로 저장
ex) 654,321 -> S = [1, 2, 3, 4, 5, 6]으로 저장
6 = S[5]
5 = S[4]
4 = S[3]
3 = S[2]
2 = S[1]
1 = S[0]
- 𝑛개의 자릿수(digit) 각각을 더하면서 올림수(carry)를 고려
Python 코드 (덧셈)
정의
def ladd (u, v): # long add(긴덧셈)
n = len(u) if (len(u) > len(v)) else len(v) #삼항식
#초기값
result = []
carry = 0
for k in range(n):
i = u[k] if (k < len(u)) else 0
j = v[k] if (k < len(v)) else 0
# else 0은 4자리수와 3자리수의 덧셈에서 3자리수의 맨앞이 0을 의미
value = i + j + carry # 1차 덧셈
carry = value // 10 #올림수, // : 정수부분만
result.append(value % 10) # % : 나머지부분만
if (carry > 0):
result.append(carry)
return result
예시 코드
u = [6, 7, 8, 9]
v = [3, 4, 5]
print(9876 + 543)
print(ladd(u, v)[::-1])
u = [2, 3, 8, 7, 6, 5]
v = [3, 2, 7, 3, 2, 4, 9]
print(567832 + 9423723)
print(ladd(u, v)[::-1])
큰 정수의 곱셈
기본 내용
- 분할정복법 (재귀호출 4번으로 효율성은 의미가 없다.)
4번 : xw, wz, yw, yz
리스트를 이용하여 각 자리수(digit)를 하나의 원소로 저장
ex) 654,321 -> S = [1, 2, 3, 4, 5, 6]으로 저장
6 = S[5]
5 = S[4]
4 = S[3]
3 = S[2]
2 = S[1]
1 = S[0]
def ladd (u, v): # long add(긴덧셈)
n = len(u) if (len(u) > len(v)) else len(v) #삼항식
#초기값
result = []
carry = 0
for k in range(n):
i = u[k] if (k < len(u)) else 0
j = v[k] if (k < len(v)) else 0
# else 0은 4자리수와 3자리수의 덧셈에서 3자리수의 맨앞이 0을 의미
value = i + j + carry # 1차 덧셈
carry = value // 10 #올림수, // : 정수부분만
result.append(value % 10) # % : 나머지부분만
if (carry > 0):
result.append(carry)
return result
u = [6, 7, 8, 9]
v = [3, 4, 5]
print(9876 + 543)
print(ladd(u, v)[::-1])
u = [2, 3, 8, 7, 6, 5]
v = [3, 2, 7, 3, 2, 4, 9]
print(567832 + 9423723)
print(ladd(u, v)[::-1])
기본 내용
- 분할정복법 (재귀호출 4번으로 효율성은 의미가 없다.)
4번 : xw, wz, yw, yz
- 강화된 곱셈법 (재귀호출을 3번으로 줄인다.)
3번 : xw, wz+yw, yz
Python 코드 (곱셈 - 분할정복법)
분할정복 곱셈 정의
def prod (u, v):
n = len(u) if (len(u) > len(v)) else len(v)
if (len(u) == 0 or len(v) == 0):
return [0]
elif (n <= threshold):
return lmult(u, v)
else:
m = n // 2
x = div(u, m); y = rem(u, m)
w = div(v, m); z = rem(v, m)
p1 = prod(x, w)
p2 = ladd(prod(x, z), prod(w, y))
p3 = prod(y, z)
return ladd(ladd(exp(p1, 2*m), exp(p2, m)), p3)
10^n, 몫, 나머지 정의
# 10^n
def exp (u, m):
if (u == [0]):
return [0]
else:
return ([0] * m) + u
#몫
def div (u, m):
if (len(u) < m):
u.append(0)
return u[m : len(u)]
#나머지
def rem (u, m):
if (len(u) < m):
u.append(0)
return u[0 : m]
곱셈 정의
def lmult (u, v):
i = u[0] if (0 < len(u)) else 0
j = v[0] if (0 < len(v)) else 0
value = i * j
carry = value // 10
result = []
result.append(value % 10)
if (carry > 0):
result.append(carry)
return result
예시 코드
u = [2, 3, 8, 7, 6, 5]
v = [3, 2, 7, 3, 2, 4, 9]
print(exp(u, 3))
print(div(u, 3))
print(rem(u, 3))
u = [2, 3, 8, 7, 6, 5]
v = [3, 2, 7, 3, 2, 4, 9]
print(567832 * 9423723)
print(prod(u, v)[::-1])
Python 코드 (곱셈 - 개선)
개선 곱셈 정의
def prod2 (u, v):
n = len(u) if (len(u) > len(v)) else len(v)
if (len(u) == 0 or len(v) == 0):
return [0]
elif (n <= threshold):
return lmult(u, v)
else:
m = n // 2
x = div(u, m); y = rem(u, m)
w = div(v, m); z = rem(v, m)
r = prod2(ladd(x, y), ladd(w, z))
p1 = prod2(x, w)
p3 = prod2(y, z)
p2 = lsub(r, ladd(p1, p3))
return ladd(ladd(exp(p1, 2*m), exp(p2, m)), p3)
뺄셈 정의
def lsub (u, v):
n = len(u) if (len(u) > len(v)) else len(v)
result = []
borrow = 0
for k in range(n):
i = u[k] if (k < len(u)) else 0
j = v[k] if (k < len(v)) else 0
value = i - j + borrow
if (value < 0):
value += 10
borrow = -1
else:
borrow = 0
result.append(value % 10)
if (borrow < 0):
print("음의 정수는 처리 못함.")
return result
예시 코드
u = [2, 3, 8, 7, 6, 5]
v = [3, 2, 7, 3, 2, 4, 9]
print(567832 * 9423723)
print(prod(u, v)[::-1])
print(prod2(u, v)[::-1])
출처 : 링크텍스트
Author And Source
이 문제에 관하여(큰 정수의 계산법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@9566/큰-정수의-계산법저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)