[백준 / 13705 / Python] Ax+Bsin(x)=C

2025. 5. 30. 09:44·Algorithm/백준
반응형

머리말

Baekjoon 13705번 문제(( Ax + B \sin(x) = C ))를 풀 때,
처음에는 Python 내장 math.sin()을 사용했지만 '틀렸습니다'가 발생했다.

왜 그럴까?

이 글에서는

  • math.sin()을 사용한 기존 코드
  • Decimal + 직접 테일러 전개로 구현한 정답 코드

를 비교하고,
왜 Decimal + 테일러 전개가 필요한지 쉽게 설명한다.


1. 기존 코드 (math.sin 사용)

import sys
import math

input = sys.stdin.readline

a, b, c = map(int, input().split())

l = (c - b) / a
r = (c + b) / a

for _ in range(80):
    m = (l + r) / 2
    V = a * m + b * math.sin(m)
    if V < c:
        l = m
    else:
        r = m

U = 1_000_000
D = 0.5
result = (U * r + D) // U / 1_000_000
print(f"{result:.6f}")

결과: Colab에서는 통과, Baekjoon에서는 '틀렸습니다'


2. 정답 코드 (Decimal + sin 직접 구현)

import sys
from decimal import Decimal, getcontext

input = sys.stdin.readline

getcontext().prec = 50  # Decimal 정밀도 설정

def sin(x):
    PI2 = Decimal('6.283185307179586476925286766559')
    x %= PI2

    res = x
    term = x
    sign = -1

    for d in range(2, 30, 2):
        term = term * x * x / (d * (d + 1))
        res += sign * term
        sign *= -1

    return res

a, b, c = map(int, input().split())

a = Decimal(a)
b = Decimal(b)
c = Decimal(c)

l = (c - b) / a
r = (c + b) / a

for _ in range(80):
    m = (l + r) / 2
    V = a * m + b * sin(m)
    if V < c:
        l = m
    else:
        r = m

U = Decimal('1000000')
D = Decimal('0.5')
ans = (U * r + D) // 1 / U

print(f"{ans:.6f}")

결과: Baekjoon에서도 '맞았습니다' 통과


3. 왜 math.sin()은 안 되는가?

(1) math.sin()은 float64 기반

  • Python의 math.sin(x)는 float64 (소수점 15자리 정도) 정확도를 가진다.
  • 그런데 문제는, (A \times x + B \times \sin(x)) 계산 결과가
    소수점 6자리 반올림 기준에서 아주 미세하게 차이날 수 있다는 것!

(예: 19.44178699999... vs 19.44178700000...)

  • 이 미세한 오차가 Baekjoon 채점기에서는 '틀렸습니다'가 된다.

(2) 해결: Decimal + 직접 테일러 전개

  • Python의 Decimal 모듈은 원하는 만큼 정밀도를 설정할 수 있다.
  • 직접 테일러 전개를 하면
    • 정밀하게 (\sin(x)) 값을 계산할 수 있고
    • 문제 출제자 채점 기준과 일치할 수 있다.

4. 추가 주의사항

  • Decimal에서도 sin(x)는 직접 구현해야 한다 (math.sin 사용 금지)
  • 고정소수점 반올림도 수동으로 처리해야 한다
    ans = (U * r + D) // 1 / U
  • 이진탐색은 80회 반복이면 충분하다

5. 마무리 정리

항목 기존 코드 수정한 코드
실수 처리 방식 float64 (math.sin) Decimal 50자리
sin 계산 방식 math.sin 사용 테일러 전개 직접 구현
오차 발생 여부 있을 수 있음 거의 없음
최종 결과 틀렸습니다 맞았습니다

✅ 결론

Python으로 부동소수점 정확한 계산이 필요할 때는 Decimal을 사용해야 한다.
특히 sin / cos / tan 계산은 직접 구현해야 오차를 제어할 수 있다.

✨ 앞으로 부동소수점 문제에서는 Decimal + 테일러 전개를 기억하자!

반응형
저작자표시 비영리 변경금지 (새창열림)

'Algorithm > 백준' 카테고리의 다른 글

[백준 / 2143 / Python] 두 배열의 합  (0) 2025.06.13
[백준 / 27172 / Python] 수 나누기 게임  (0) 2025.06.13
[백준 / 1647 / Python] 도시 분할 계획  (0) 2025.06.10
[백준 / 27440 / Python] 1 만들기  (0) 2025.05.30
[백준 / 2166 / Python] 다각형의 면적  (0) 2025.05.28
'Algorithm/백준' 카테고리의 다른 글
  • [백준 / 27172 / Python] 수 나누기 게임
  • [백준 / 1647 / Python] 도시 분할 계획
  • [백준 / 27440 / Python] 1 만들기
  • [백준 / 2166 / Python] 다각형의 면적
Kun Woo Kim
Kun Woo Kim
안녕하세요, 김건우입니다! 웹과 앱 개발에 열정적인 전문가로, React, TypeScript, Next.js, Node.js, Express, Flutter 등을 활용한 프로젝트를 다룹니다. 제 블로그에서는 개발 여정, 기술 분석, 실용적 코딩 팁을 공유합니다. 창의적인 솔루션을 실제로 적용하는 과정의 통찰도 나눌 예정이니, 궁금한 점이나 상담은 언제든 환영합니다.
  • Kun Woo Kim
    WhiteMouseDev
    김건우
  • 깃허브
    포트폴리오
    velog
  • 전체
    오늘
    어제
  • 공지사항

    • [인사말] 이제 티스토리에서도 만나요! WhiteMouse⋯
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 분류 전체보기 (100) N
      • Frontend Development (39) N
      • Backend Development (21) N
      • Algorithm (33) N
        • 백준 (11) N
        • 프로그래머스 (17)
        • 알고리즘 (5)
      • Infra (1)
      • 자료구조 (3)
  • 링크

    • Github
    • Portfolio
    • Velog
  • 인기 글

  • 태그

    frontend development
    tailwindcss
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Kun Woo Kim
[백준 / 13705 / Python] Ax+Bsin(x)=C
상단으로

티스토리툴바