[백준]10834_벨트(Python)

차보경·2022년 12월 2일
0

백준

목록 보기
19/20
post-thumbnail

문제

  • 벨트
  • 기둥을 연결하는 벨트의 회전 방향과 각 회전 비율이 주어짐. 첫번째 기둥이 1바퀴 돌 때, 마지막 기둥의 회전 횟수와 방향을 출력하기

CODE

import sys
input = sys.stdin.readline
r_d = 0
r_n = 1

for i in range(int(input())):
    num = list(map(int,input().split()))
    r_n = int(r_n * num[1]/num[0])
    r_d = (r_d + num[2]) % 2

print(r_d, r_n)
  • 횟수 : 기존 값 * 회전 비율
  • 방향 : 1이 나오면 다시 0이 되도록 각 수를 더해서 2의 나머지 값으로 처리함

배운 것

  • 실수 오차 : 처음에 횟수를 r_n = int(r_n * (num[1]/num[0])) 이렇게 먼저 해당 벨트로 연결된 비율을 먼저 구하고 앞의 수와 곱해줬는데, 이러면 13점이 나오게 된다.
    왜인가 알아보니, 컴퓨터는 실수를 정확하게 처리하지 못해 오차가 발생하기 때문이었다.

    ratio *= 1.0 / 49.0;
    컴퓨터는 실수를 정확하게 처리하지 못하지만, 나름대로 정밀하게 계산하려고 합니다. 1.0 / 49.0이 레지스터에 저장되는 값은
    0.0204081632653061208204636756136096664704382419586181640625입니다. 1/49의 참값
    0.0204081632653061224489795918367346938775510204081632653061224489...와 비슷해보이지만, 뒤쪽을 보면 레지스터에 저장된 값이 23 / (49 × 258)만큼 부족한 것을 확인하실 수 있습니다. 이게 중요하냐고요? 그 다음 과정을 보겠습니다.
    ratio에 저장되어 있던 정수 49를 불러와서
    0.0204081632653061208204636756136096664704382419586181640625와 곱하면, 레지스터에 저장되는 값은 0.99999999999999988897769753748434595763683319091796875입니다. 방금 부동소수점 정밀도의 한계로 또 9 / 258이 감소했네요. 마지막으로, 이렇게 계산한 값을 ratio 변수에 저장하려니, ratio는 정수네요. 따라서
    0.99999999999999988897769753748434595763683319091796875를 정수 단위로 버림한 0이 저장됩니다. 출처 : 백준 질문

내용이 길지만 정리하면 계산 순서에 따라 발생하는 실수 오차가 int처리시 값의 변형을 일으킨다는 것이다.
꼭 하나하나 식을 쓸 때도 깊게 생각해보고 처리해야겠다.

  • sys.stdin.readline의 속도 차이

    짧은 코드인데도 저렇게 차이가 나는걸 보면, sys를 생활화해야겠다는 생각이든다.

  • 그리고 다른사람 코드를 보니 0 = False인 것을 이용해서

c = False
for i in range(n):
    a, b, w = map(int, sys.stdin.readline().split())
    if w: c = not c

이런식으로 not c를 이용해 바꿔주는 것을 봤다. 크.... 똑똑이...

profile
차보의 Data Engineer 도전기♥ (근데 기록을 곁들인)

0개의 댓글