여니의 취준 준비/코딩테스트 (Python)

[2417] 정수 제곱근 In python

여니's 2022. 3. 4. 12:17

> 이분탐색

> 수학

 

 

1. 수학적인 공식을 이용하여 푼 방법

 

* 틀린 코드 *

아래 코드와 같이 했는데, 90% 가까이 성공하다 틀렸습니다 파티가 일어났다..

왜지? 왜 안되는거지?라는 의문을 가지고

질문 게시판을 뒤적인 결과

 

부동소수점 오차 문제 때문이란다..

f,e=0,int(input())**.5
if e-int(e)==0:
    print(e)
else:
    print(int(e)+1)

일단 컴퓨터가 실수를 표현하는 방식에 대해 알아야한다.

컴퓨터는 모든 수를 2진수(0과 1)로 표현한다.

정수는 표현이 간단하지만,

실수는 그리 간단하지 않다.

 

실수 표현 방식에는 두 가지 방식이 존재한다.

1. 고정 소수점 방식

2. 부동 소수점 방식

 

 

(1) 고정 소수점 방식

실수를 정수부와 소수부로 나눈다. 

소수부의 자릿수를 미리 정하고

고정된 자릿수의 소수를 표현하는 것이다.

 

이 방식의 단점

- 표현할 수 있는 범위가 매우적다.

- 정밀도가 낮다.

- 소규모 시스템에서만 쓰인다.

 

 

(2) 부동 소수점 방식

실수를 가수부와 지수부로 나누어 표현한다.

부동 소수점 방식은

실수를 -(가수부)*2^지수부-127,+(가수부)*2^지수부-127로 표현한다.

대부분의 시스템에서는 부동 소수점 방식으로 실수를 표현할 수 있다.

매우 큰 실수까지도 표현이 가능하다.

 

지수부 : 가수의 어디쯤에 소수점이 있는지 나타내는 부분

가수부 : 실수의 실제 값을 표현하는 부분

 

이 방식의 단점

- 항상 오차가 존재한다 ** 

해당 공식을 사용하게 되면 10진수를 정확하게 표현할 수 없다. 

왜냐하면 실수는 무한히 많은데

이 실수를 유한개의 비트로 표현해내다보니

근삿값으로 표현을 하기 때문이다. 

 

 

컴퓨터에서 실수를 가지고 수행하는 모든 연산에서는

언제나 이런 작은 오차가 발생한다.

 

 


부동 소수점 오차를 해결하는 방법

(1) decimal.Decimal 

decimal 모듈은 

빠르고 정확하게 반올림 된 10진수 부동 소수점 산술을 지원한다. 

 

decimal.Decimal("3.14")*3

> 9.42 

정확하게 값이 산출된다.

 


실수의 제곱근 결과 구하기 > 부동 소수점 오차 안 나게끔

decimal.Decimal("3.14").sqrt()

 

e%1==0 -> e의 값이 정수일 경우

import decimal
n = int(input())
e=decimal.Decimal(str(n)).sqrt()
if e%1==0:
    print(int(e))
else:
    print(int(e) + 1)