Chapter
1.약수와 배수
(1) 약수와 소수
(2) 소인수와 소인수분해
(3) 공약수
(4) 공배수
2.진법
(1) n진수
(2) 진수의 변환
3.수열
(1) 등차수열
약수란 어떤 수를 나누어 떨어지게 하는 수를 말한다.
예를 들어, 2는 1과 2로 나누어 떨어지므로 1,2는 2의 약수라고 한다.
이런 식으로 약수를 몇 가지 구해보면
8 → (1, 2, 4, 8)
15 → (1, 3, 5, 15)
48 → (1, 2, 3, 4, 6, 8, 12, 16, 24, 48)
이런 식으로 구할 수 있다.
파이썬으로도 for문을 이용하면 약수를 구할 수 있다.
사용자가 입력한 수를 inputNumber의 변수로 초기화한 후 이의 약수를 구해보자.
inputNumber = int(input('0보다 큰 정수 입력: '))
for number in range(1, (inputNumber+1)):
if inputNumber % number == 0:
print('{}의 약수: {}'.format(inputNumber, number))
이런 식으로 for문의 범위를 inpuNumber만큼 설정한 다음, inputNumber를 1씩 증가하는 수들로 나누어 떨어진 다면 약수로 출력한다.
소수는 1과 자신만을 약수로 가지는 수를 말한다. (단, 1은 제외) 2,3,5,7,11,... 등과 같은 수들이 해당된다.
약수(인수) 중에서 소수인 숫자를 소인수라고 한다. 예를 들어, 8의 약수들을 구했을 때 1,2,4,8이 나온다. 그런데 이들 중 소수는 2밖에 없으므로 8의 소인수는 2가 해당된다.
몇 가지 예를 들어 소인수를 구해보자.
12 → (1, 2, 3, 4, 6, 12) → 소인수: (2, 3)
36 → (1, 2, 3, 4, 6, 9, 12, 18, 36) → 소인수: (2, 3)
41 → (1, 41) → 소인수: (41)
1보다 큰 정수를 소인수의 곱으로 나타낸 것이다. 앞에서 구한 수들을 소인수를 이용해서 소인수분해 해보자.
12 = 2² x 3
36 = 2² x 3²
41 = 41
수가 너무 커서 소수를 구하기가 어려울 때에는 작은 수부터 나누어서 더이상 나누어지지 않을 때까지 구하는 방법도 있다. 2520과 같은 큰 수를 소인수분해하고 싶을 때에는

이런 식으로 구하면 쉽게 구할 수가 있다.
2520 = 2³ x 3² x 5 x 7
이를 파이썬을 이용해서 구해보면, 마찬가지로 더 이상 나누어 떨어지지 않을 때까지 1씩 큰 수로 나누면 된다.
inputNumber = int(input('1보다 큰 정수 입력: '))
n = 2
while n <= inputNumber:
if inputNumber % n == 0:
print('소인수:{}'.format(n))
inputNumber /= n
else:
n += 1

공약수란, 두 개 이상의 수에서 공통된 약수들을 말하고 이들 중 가장 큰 수를 최대공약수라고 한다.
소인수분해를 이용해서 구해보면,
36 = 2² x 3²
60 = 2² x 3 x 5
36과 60을 각각 소인수분해해보면 이와 같다. 이렇게 소인수분해한 다음, 공통된 인수들의 곱이 최대공약수가 된다.
따라서 2² x 3 = 12가 최대공약수가 되는 것이다. 그리고 이 최대공약수의 약수가 공약수가 된다.
12 → (1, 2, 3, 4, 6, 12)
혹은, 너무 수가 크거나 복잡할 때에는 나누어 떨어지는 공통의 소수들로 하나씩 나누면 쉽게 구할 수 있다.

이 때에는 공통으로 나눈 몫들을 곱했을 때 최대공약수가 된다.
파이썬을 이용해서 구해보자.
# num1 < num2로 가정함
num1 = int(input('1보다 큰 정수 입력: '))
num2 = int(input('1보다 큰 정수 입력: '))
maxNum = 0
for i in range(1, (num1 + 1)):
if num1 % i == 0 and num2 % i == 0:
print('공약수: {}'.format(i))
maxNum = i
print(f'최대공약수: {maxNum}')
for문을 이용해서 두 개의 수가 모두 나누어 떨어지는 수들을 약수로 구한다음 마지막 수(가장 큰 몫)을 최대공약수로 출력한다.

유클리드 호제법을 이용한 해법도 있다. 큰 수를 작은 수로 나눈 다음 나오는 나머지가 나온 다면, 나눈 값을 나머지로 계속 나누어서 0이 될 때의 나눈 값이 최대공약수가 된다.
앞의 36과, 60을 예로 들자.
60 ÷ 36 = 136 + 24
나머지 24를 나눈 값 36으로 다시 나눈다.
36 ÷ 24 = 124 + 12
나머지 12를 나눈 값 24로 다시 나눈다.
24 ÷ 12 = 2*12 + 0
나머지가 0이 되었을 때의 나눈 값, 12가 최대공약수가 된다.
파이썬으로 코드를 짜보면
num1 = int(input('1보다 큰 정수 입력: '))
num2 = int(input('1보다 큰 정수 입력: '))
temp1 = num1
temp2 = num2
while temp2 > 0:
temp = temp2
temp2 = temp1 % temp2
temp1 = temp
print(f'{num1}, {num2}의 최대공약수: {temp1}')

이런 식으로 나머지를 이용해서 구할 수 있다.
두 개이상의 수 사이의 공통된 배수를 공배수라고 하며, 공배수 중 가장 작은 수를 최소공배수라고 한다.
소인수분해를 이용해서 공배수를 구할 수 있는데,
10 = 2 x 5
12 = 2² x 3
최소공약수가 공통된 소인수들의 곱이었다면, 최소공배수는 공통된 소인수들의 곱뿐만 아니라 나머지 소인수들까지 전부 곱해서 값을 구한다.
따라고 최소공배수는 2² x 3 x 5 = 60이 된다.
나눗셈을 이용해서 최소공배수를 찾을 수 있다.

공통으로 나눈 몫의 값들과 함께 나머지를 모두 곱해서 최소공배수를 구한다. 따라서 10과 12의 최소공배수는 2 x 5 x 6 = 60이 된다.
파이썬으로 최소공배수를 구하면 다음과 같다.
num1 = int(input('1보다 큰 정수 입력: '))
num2 = int(input('1보다 큰 정수 입력: '))
maxNum = 0
for i in range(1, (num1+1)):
if num1 % i == 0 and num2 % i == 0:
print(f'공약수: {i}')
maxNum = i
print(f'최대 공약수: {maxNum}')
minNum = (num1 * num2) // maxNum
print(f'최대공배수: {minNum}')
최소공배수의 경우에는 앞에서 구한 최소공약수를 이용해서 구할 수 있는데, 최대공약수를 먼저 구한 다음 구하고자 하는 수들을 곱한다음 최소공약수로 나눈다. 이유는 나눗셈을 이용한 방법에서 알 수 있듯이 공통으로 나눈 몫은 딱 한번씩만 곱해주기 때문에 두 수의 곱에서 최소공약수를 나누면 최소공배수를 구할 수 있다.
진법이란 특정 숫자 몇 개를 사용하여 수를 표시하는 것이다. 우리가 일상생활에서 사용하는 수들은 10진법을 이용한 것으로 0~9까지 순서로 총 10개의 수를 이용해서 표시한다.
만약, 2진수를 사용한다면 0~1까지의 2개의 수를, 8진수라면 0~7까지의 8개의 수를, 16진수의 경우에는 0~9까지 10개, 나머지 6개는 a~f의 문자를 사용해서 표현하는 말하는 것이다.
10진수를 n진수로 나눌 때에는 수를 n으로 나누어 나머지를 이용해서 수를 표현할 수 있다. 30을 예시로 2,8,16진수로 각각 변환해 보자.

2진수의 경우는 11110,
8진수의 경우는 36,
16진수의 경우는 1e가 된다.(10부터 15까지 a~f)
파이썬으로도 함수를 이용해서 쉽게 변환할 수 있다.
print(f'2진수: {bin(dNum)}') #'0b'로 시작하는 문자열
print(f'8진수: {oct(dNum)}') #'0o'로 시작하는 문자열
print(f'16진수: {hex(dNum)}') ##'0h'로 시작하는 문자열
혹은 format함수를 이용해서 옵션으로 변환할 진수들의 이니셜을 넣어준다.
print('2진수: {}'. format(format(dNum, '#b')))
print('8진수: {}'. format(format(dNum, '#o')))
print('16진수: {}'. format(format(dNum, '#x')))
print('2진수: {}'. format(format(dNum, 'b')))
print('8진수: {}'. format(format(dNum, 'o')))
print('16진수: {}'. format(format(dNum, 'x')))
print('{0:#b}, {0:#o}, {0:#x}'.format(dNum,dNum,dNum))
거듭제곱을 이용해서 10진수로 변환할 수 있다.
n진수의 뒷자리부터 차례대로 m-1자리라로 여겨서 n의(m-1) * 자리수를 해주면 된다. 2,8,16진수를 차례대로 10진수로 변환해보자.
11110 → (1x2⁴) + (1X2³) + (1X2²) + (1X2¹) + (0X2⁰) = 30
36 → (3x8¹) + (6x8⁰) = 30
1e → (1x16¹) + (14x16⁰) = 30
파이썬의 경우에도 함수를 이용해서 간단하게 변환할 수 있다.
# n진수 -> 10진수
print('2진수(0b11110) -> 10진수({})'.format(int('0b11110',2)))
print('8진수(0o36) -> 10진수({})'.format(int('0o36',8)))
print('16진수(0x1e) -> 10진수({})'.format(int('0x1e',16)))
# n진수 -> m진수
print('2진수(0b11110) -> 8진수({})'.format(oct(0b11110)))
print('2진수(0b11110) -> 10진수({})'.format(int(0b11110)))
print('2진수(0b11110) -> 16진수({})'.format(hex(0b11110)))
print('8진수(0o36) -> 2진수({})'.format(bin(0o36)))
print('8진수(0o36) -> 10진수({})'.format(int(0o36)))
print('8진수(0o36) -> 16진수({})'.format(hex(0o36)))
수열이란, 규칙성을 가지고 나열되어 있는 수들을 말한다.
등차수열의 경우에는 연속된 두 항의 차이가 일정한 수열을 말한다.
{2,4,6,8,.....} 과 같은 수열이 있다면 +2의 차이로 수가 나열되어 있음을 알 수 있다. 이때의 차이를 공차(d)라고 한다.
수열의 경우는 일반항 a[n]의 공식을 이용해서 n번째 항의 수를 쉽게 구할 수 있다. 뿐만 아니라 n번째 값까지의 합 S[n]도 구할 수 있다.

파이썬을 이용해서 n번째 항을 구하면 다음과 같다.
inputN1 = int(input('a1 입력: '))
inputD = int(input('공차 입력: '))
inputN = int(input('n 입력: '))
valueN = 0
n = 1
while n <= inputN:
if n == 1:
valueN = inputN1
print('{}번째 항의 값: {}'.format(n,valueN))
n += 1
continue
valueN += inputD
print('{}번째 항의 값: {}'.format(n, valueN))
n += 1
print('-'*50)
print('{}번째 항의 값: {}'.format(inputN, valueN))

먼저 첫 번째 항의 값을 할당한 후, 그 다음부터는 할당연산자를 이용해서 n항까지 공차를 계속 더해주면 된다.
혹은 일반항의 공식을 이용해서 수를 대입해서 간단하게 구할 수도 있다.
n1 = int(input('a1입력: '))
d = int(input('공차 입력: '))
n = int(input('n입력: '))
an = n1 + (n-1)*d
print('등차수열 {}번쨰 항의 값은 {}이다'.format(n,an))

마찬가지로 while문과 일반공식을 이용해서도 n까지 항의 합을 구할 수 있다.
inputN1 = int(input('a1 입력: '))
inputD = int(input('공차 입력: '))
inputN = int(input('n 입력: '))
valueN = 0
sumN = 0
n = 1
while n <= inputN:
if n == 1:
valueN = inputN1
sumN += valueN
print(f'{n}번째 항까지의 합: {sumN}')
n += 1
continue
valueN += inputD
sumN += valueN
print(f'{n}번째 항까지의 합: {sumN}')
n += 1
print(f'{inputN}번째 항까지의 합: {sumN}')

a1 = int(input('a1입력: '))
n = int(input('n입력: '))
d = int(input('공차 입력: '))
an = a1 + (n-1)*d
sn = n*(a1+an)/2
print(f'{n}번쨰 항은 {an}이고, {n}까지 항의 합은 {sn}')
