• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

부동소수점의 오차에 대해 제가 이해한 것인지 궁금합니다.

21.01.28 18:37 작성 조회수 333

0

영상 14:30 쯤에 double을 비교해주시고 차이를 보는 방법을 알려주셨습니다.

혹시 차이말고 값을 알고싶어서 setprecision(20)을 통해서는 값을 받았습니다. 이렇게 되면 오차가 더 커지게되고

그 숫자로 다시 차이를 알게되었을 때 오차가 더더욱 커지게 된다고 이해를 했는데 맞는 것인지 궁급합니다.

또 setprecision(20)을 통해 받은 double d1의 값과 실제 d1의 값이 같고 출력값이 다른걸로 이해를 했는데 맞는 것인지 궁금합니다.

답변 3

·

답변을 작성해보세요.

1

안소님의 프로필

안소

2021.01.28

안녕하세요.

작성해주신 두 질문이 이해가 잘 되지 않습니다..ㅠㅠ  혹시 아래 설명으로도 이해가 되지 않으시다면 테스트 해보신 코드와 좀 더 자세한 설명 덧붙여 주시기를 부탁드립니다.

우선 setprecision 에 잘못 알고 계신 것 같아서 드리고 싶은 말씀은 setprecision은 '입출력'을 조작하는데 쓰이는 함수입니다.  그저 cout을 통한 모든 출력에 대한 정밀도를 조절해주는 함수라고 생각해주시면 됩니다.  '출력'의 정밀도를 조절하는 함수입니다. specision은 어떤 값을 주는 함수도 아니며 double의 오차나 값에 영향 주지 않습니다. 그저 '출력'을 얼마나 정밀하게 하느냐를 조절해줄 뿐인 함수입니다.

double d 에 0.1 이라는 실수를 대입했다면, 사실 이 0.1은 겉으론 0.1 이렇게 두자리로 표기 되고 있긴하지만 사실 0.1에 최대한 가까운 수로 만들어진 것에 불과합니다. double이 표현한 0.1은 실제론 0.10000000000000001 입니다. 이진수의 조합으로 십진수 소수들을 표현하기 떄문에 그렇습니다. cout에  setprecision(20) 정보를 흘려준다면 앞으로 출력할 모든 수들을 20자리로 출력하라고 알려주는 것일 뿐이고, 이런 상태를 가진 cout을 통해 double을 출력하게 되면 0.10000000000000001 대충 이런식으로 출력 정밀도가 조절되어 숨겨져 있던 소수점 가장 마지막 자리의 1이 등장하게 된 것 뿐입니다. double은 원래 내부적으론 0.10000000000000001 값을 가지는 상태입니다.

cout 출력 정밀도 기본값은 6입니다. 즉 최대 6자리까지만 출력되도록 기본적으로 그렇게 설정되어있습니다. 그래서 setprecision을 안쓰면 평소엔 0.10000 즉, 0.1 이정도까지만 출력되는 것일 뿐이에요.

setpresicion 로 출력 정밀도 조절해주기 전입니다.  디버깅 내용을 보시면 d1과 d2은 각각 실제로 보유하는 값은 d1은 0.010000000000005116, d2는 0.0099999999999997868 입니다. 원래 이 값을 가지고 있습니다. 각각 0.01 에 근접할 수 있도록 최대한 노력한(?)값들인 것이에요. 근데 cout은 기본적으로 정밀도 6을 기준으로 출력해줄 뿐이기 때문에 실제 d1, d2값을 전부 출력해주는게 아니라 이 d1, d2 값을 정밀도 6 버전으로 출력해줄 뿐입니다. 그래서 0.01이 출력된 것입니다. d1과 d2가 실제로 0.01이라는게 아니라 그저 cout 출력 정밀도 기준에 따라 0.01까지만 출력된 것일 뿐입니다.

정밀도 20으로 출력되게끔 하니 20자리까지 출력되어 d1과 d2의 원래 값들이 전부 출력되네요. (보아하니 double인 d1과 d2가 다 담지 못했던 뒷 부분들까지도 출력이 되네요. ) 

말씀하신 오차의 의미가 '콘솔 창에 출력된 값'의 오차를 말씀하시는 것이면 출력 정밀도 값을 높일 수록 오차가 늘어난다고 말할 수 있겠네요. 근데 두 double 자체끼리의 오차를 말씀하시는 것이라면 두 오차는 변함 없습니다. specision이랑 상관 없습니다.

0

안소님의 프로필

안소

2021.01.29

네 맞습니다!! 사진에서 보이다시피 d1은 원래 0.010000000000000000000516 이런 값인데 cout 의 "출력 정밀도"를 올려준 것 뿐이라 d1이 표현한 0.01의 숨겨진 부분들까지도 출력된 것이라고 생각해주시면 될 것 같아요! 점점 오차가 생기는 것이 아니라 출력의 정밀도가 바뀐 것 뿐입니다. d1값은 고정이며 오차도 원래 그 오차인 것입니다.

0

nurugji님의 프로필

nurugji

질문자

2021.01.29

자세한 답변 감사드립니다.

d1의 의 정밀도를 늘려서 d1의 값이 0.01에서 점점 오차가 생기는 것처럼 보이지만 >> 0.01000....1

디버깅을 통해서 본것처럼 원래 d1은 0.01에 최대한 가까운수로 만들어진 것에 불과하기 때문에

정밀도를 늘리면 d1값이 달라지는 것이 아닌 숨겨진 d1의 모습을 보여주는 것으로 이해했는데 맞는 것인가요?