8

제곱근을 근사하는 함수를 작성하려고했습니다. (수학 모듈이 있다는 것을 알고 있습니다 ... 직접하고 싶습니다.) 부동 소수점 산술에 의해 엉망이되었습니다. 어떻게 피할 수 있니?부동 소수점 오류를 방지하는 방법은 무엇입니까?

>>> sqrt(4) 
2.0000000000000013 
>>> sqrt(9) 
3.00999999999998 

난 그냥 round()을 사용할 수 있습니다 실현,하지만이 정말 정확하게 할 수 있도록하려면이 사용

def sqrt(num): 
    root = 0.0 
    while root * root < num: 
     root += 0.01 
    return root 

이 결과가 있습니다. 나는 6 자리 또는 7 자리로 계산할 수 있기를 원합니다. 내가 반올림하면 그건 불가능 해. 파이썬에서 부동 소수점 계산을 올바르게 처리하는 방법을 알고 싶습니다.

+0

아마 시도 [진] (http://docs.python.org/2/library/decimal.html) 모듈을 계산하기위한 "뉴턴의 방법"을 찾아 정밀도를 위해 설계된가요? – Michael0x2a

답변

15

이것은 실제로 파이썬과 아무 관련이 없습니다. 하드웨어의 바이너리 부동 소수점 산술을 사용하여 모든 언어에서 동일한 동작을 볼 수 있습니다. 먼저 read the docs.

이 글을 읽은 후에는 이 아니고이 아니라 코드의 1/100을 더 잘 이해할 것입니다.

>>> from decimal import Decimal 
>>> Decimal(.01) 
Decimal('0.01000000000000000020816681711721685132943093776702880859375') 

그 문자열은 이진 부동 (C에서 "이중 정밀도")의 정확한 진수 값을 보여줍니다 근사치를 정확한 소수점 값 0.01 : 이렇게하면 추가 정확히 것입니다. 당신이 실제로 추가하는 것은 1/100보다 약간 큰 것입니다.

부동 소수점 오류 제어는 "수치 해석"이라는 필드이며 매우 크고 복잡한 주제입니다. 부동 소수점은 10 진수 값의 근사치에 불과하다는 사실에 깜짝 놀랐다면 decimal 모듈을 사용하십시오. 그것은 당신에게 "얕은"문제의 세계를 빼앗아 갈 것입니다. 다음

from decimal import Decimal as D 

def sqrt(num): 
    root = D(0) 
    while root * root < num: 
     root += D("0.01") 
    return root 

: 예를 들어, 기능이 작은 수정을 부여

>>> sqrt(4) 
Decimal('2.00') 
>>> sqrt(9) 
Decimal('3.00') 

그것은 정말 더 정확한 건 아니지만, 지금은 정확히 하나 하나 를 추가 있기 때문에 간단한 예제 덜 놀라운 일이 될 수있다 -백.

부동 소수점을 고수하고 인 것을 이진 부동 소수로 정확하게 표현할 수 있습니다 : I/2**J 형식의 값. 예를 들어, 0.01을 더하는 대신 0.125 (1/8) 또는 0.0625 (1/16)를 더하십시오.

그리고있는이, 제곱근 ;-)에게

+0

레코드의 경우 문서를 읽었으며 이진 표현을 저장하면 전체 부동 소수점 정확도에 대해 이미 알고있었습니다. 나는 뉴튼의 방법을 잊어 버렸다. 여기에 내 모든 질문을 피킹하고있어! 내 운 좋은 날을 발견했을 때. 어떻게 Decimal 모듈이 작동하는지 궁금합니다. 출처를 읽는 것 외에 다른 방법을 찾을 수 있습니까? – Aerovistae

+1

음,'decimal'은 원래 파이썬으로 작성되었으며 10 진수 목록 (0, 1, 2, ..., 9)을 처리했습니다. 우리가 종이에서 산술을 어떻게하는지 에뮬레이트합니다! "부동 소수점"은 표현에 (십진수) 지수를 추가 한 다음 매우 조심해야합니다 .-) 현재'decimal' 모듈은 C로 코딩되어 있으며 훨씬 더 모호합니다 :-( –

+0

내가 말했듯이 십진법 모듈을 사용하여'4 - 3.2'를 해결합니다. A = 소수 (4) B = 소수 (3.2) 하지만 A - B 결과 십진수 ('0.7999999999999998223643160600') – Srinesh

관련 문제