파이썬 자료구조와 알고리즘(1)-숫자
업데이트:
1. 정수
(999).bit_length() # 정수를 나타내는 데 필요한 바이트 수
10
# 문자열을 정수로 변환 or 진법 변환
s = '11'
d = int(s)
print(d)
b = int(s,2)
print(b)
11
3
2. 부동소수점
- 부호
- 유효 숫자 자릿수
- 지수
로 이루어짐
2.1 부동소수점끼리 비교하기
부동소수점은 이진수 분수로 표현된다.
unittest
모듈의assertAlmostEqual()
메서드-
def a(x, y, places=7): return round(abs(x-y), places) == 0
2.2 정수와 부동소수점 메서드
divmod(x, y)
: x를 y로 나눌 때, 몫과 나머지를 반환
divmod(45, 6)
(7, 3)
round(x, n)
- n이 음수 : x를 n만큼 반올림한 값
- n이 양수 : x를 소수점 이하 n자리로 반올림한 값
round(100.96, -2)
100.0
round(100.965, 2)
100.97
# 부동소수점을 분수로
2.75.as_integer_ratio()
(11, 4)
3. 복소수
z.real, z.imag, z.congugate
와 같은 메서드import cmath
4. fraction 모듈
- 분수를 다루기 위한 모듈
from fractions import Fraction
def rounding_floats(number1, places):
return round(number1, places)
def float_to_fractions(number):
return Fraction(*number.as_integer_ratio())
def get_denominator(number1, number2):
""" 분모를 반환한다."""
a = Fraction(number1, number2)
return a.denominator
def get_numerator(number1, number2):
""" 분자를 반환한다."""
a = Fraction(number1, number2)
return a.numerator
def test_testing_floats():
number1 = 1.25
number2 = 1
number3 = -1
number4 = 5/4
number6 = 6
assert(rounding_floats(number1, number2) == 1.2)
assert(rounding_floats(number1*10, number3) == 10)
assert(float_to_fractions(number1) == number4)
assert(get_denominator(number2, number6) == number6)
assert(get_numerator(number2, number6) == number2)
print("테스트 통과!")
if __name__ == "__main__":
test_testing_floats()
테스트 통과!
5. decimal 모듈
- 정확한 10진법의 부동소수점 숫자가 필요한 경우
- immutable type인
decimal.Decimal
사용
sum(0.1 for i in range(10)) == 1.0
False
from decimal import Decimal
sum(Decimal('0.1') for i in range(10)) == Decimal('1.0')
True
sum(Decimal('0.1') for i in range(10)) == 1.0
True
6. 2진수, 8진수, 16진수
# 정수 i의 2진수 문자열 반환
bin(999)
'0b1111100111'
oct(999)
'0o1747'
hex(999)
'0x3e7'
7. 연습문제
7.1 진법 변환
# 다른 진법의 숫자를 10진수로 변환
def convert_to_decimal(number, base):
multiplier, result = 1, 0
while number > 0:
result += number%10 *multiplier
multiplier *= base
number = number // 10
return result
if __name__ == '__main__':
print(convert_to_decimal(1001, 2))
9
# 10진수를 다른 진법의 수로 변환
def convert_from_decimal(number, base):
multiplier, result = 1, 0
while number > 0:
result += number % base * multiplier
multiplier *= 10
number = number // base
return result
print(convert_from_decimal(9,2))
1001
# base가 10보다 큰 경우
# 10진법 수를 20이하의 진법으로 변환
def convert_from_decimal_larger_bases(number, base):
strings = '0123456789ABCDEFGHIJ'
result = ''
while number > 0:
digit = number % base
result = strings[digit] + result
number = number // base
return result
print(convert_from_decimal_larger_bases(31, 16))
1F
# 재귀 함수를 사용한 진법 변환
def convert_dec_to_any_base_rec(number, base):
convertString = '0123456789ABCDEF'
if number < base:
return convertString[number]
else:
return convert_dec_to_any_base_rec(number//base, base) + convertString[number % base]
print(convert_dec_to_any_base_rec(9,2))
1001
7.2 최대공약수
def finding_gcd(a, b):
while b != 0:
result = b
a, b = b, a % b
return result
print(finding_gcd(12, 21))
3
7.3 random 모듈
7.4 피보나치 수열
import math
# 재귀를 사용하는 방법 : O(2^n)
def find_fibonacci_seq_rec(n):
if n < 2 :
return n
return find_fibonacci_seq_rec(n-2) + find_fibonacci_seq_rec(n-1)
# 반복문 사용하는 방법 : O(n)
def find_fibonacci_seq_iter(n):
if n < 2:
return n
a, b = 0, 1
for i in range(n):
a, b = b, a+b
return a
# 수식 사용하는 방법 : O(1), 70이상은 정확하지 않다
def find_fibonacci_seq_form(n):
sq5 = math.sqrt(5)
phi = (1+sq5) / 2
return int(math.floor(phi ** n / sq5))
print(find_fibonacci_seq_rec(10))
print(find_fibonacci_seq_iter(10))
print(find_fibonacci_seq_form(10))
55
55
55
# generator 이용하는 방법
# 전체 시퀀스를 메모리에 올리지 않는다.
def fib_generator():
a, b = 0, 1
while True:
yield b
a, b = b, a+b
fg = fib_generator()
for _ in range(10):
print(next(fg), end=' ')
1 1 2 3 5 8 13 21 34 55
7.5 소수
- 브루트 포스
-
제곱근을 이용
$m = \sqrt{n}, m * m = n$ 이라 가정한다.
n이 소수가 아니면,
$n = a * b$ 이므로
$m * m = a * b$ 이다.
m은 실수, n, a, b 는 자연수
- a > m 이면, b < m
- a = m 이면, b = m
- a < m 이면, b > m
세 가지 경우 모두 min(a, b) <= m이다.
따라서, m까지만 검색하여 적어도 하나의 n과 나누어 떨어지는 수가 있으면,
n이 소수가 아님을 보여준다
import math
import random
# 1. brute force
def finding_prime(number):
num = abs(number)
if num < 4 :
return True
for x in range(2, num):
if num % x == 0:
return False
return True
# 2. using sqrt
def finding_prime_sqrt(number):
num = abs(number)
if num < 4:
return True
for x in range(2, int(math.sqrt(num))+1):
if num % x == 0:
return False
return True
# 3. 페르마의 소정리
def finding_prime_fermat(number):
if number <= 102:
for a in range(2, number):
if pow(a, number-1, number) != 1:
return False
return True
else:
for i in range(100):
a = random.randint(2, number-1)
if pow(a, number-1, number) != 1:
return False
return True
def test_finding_prime():
number1 = 17
number2 = 20
print(finding_prime(17))
print(finding_prime(20))
print(finding_prime_sqrt(17))
print(finding_prime_sqrt(20))
print(finding_prime_fermat(17))
print(finding_prime_fermat(20))
True
False
True
False
True
False
import math
import random
import sys
# n비트 소수 생성 코드
def generate_prime(number=3):
while True:
p = random.randint(pow(2, number-2), pow(2, number-1)-1)
p = 2*p+1
if finding_prime_sqrt(p):
return p
generate_prime(4)
13
8. numpy
파이썬 리스트에 비해 연산이 매우 효율적이다.
댓글남기기