BOJ 2720번 세탁소 사장 동혁 파이썬

자기개발자·2022년 4월 16일
0

간단한 브론즈 문제인데 부동소수점 타입 계산할 때 생기는 오차 때문에 꽤 시간을 소용했다.

문제

미국으로 유학간 동혁이는 세탁소를 운영하고 있다. 동혁이는 최근에 아르바이트로 고등학생 리암을 채용했다.

동혁이는 리암에게 실망했다.

리암은 거스름돈을 주는 것을 자꾸 실수한다.

심지어 $0.5달러를 줘야하는 경우에 거스름돈으로 $5달러를 주는것이다!

어쩔수 없이 뛰어난 코딩 실력을 발휘해 리암을 도와주는 프로그램을 작성하려고 하지만, 디아블로를 하느라 코딩할 시간이 없어서 이 문제를 읽고 있는 여러분이 대신 해주어야 한다.

거스름돈의 액수가 주어지면 리암이 줘야할 쿼터(Quarter, $0.25)의 개수, 다임(Dime, $0.10)의 개수, 니켈(Nickel, $0.05)의 개수, 페니(Penny, $0.01)의 개수를 구하는 프로그램을 작성하시오. 거스름돈은 항상 $5.00 이하이고, 손님이 받는 동전의 개수를 최소로 하려고 한다. 예를 들어, $1.24를 거슬러 주어야 한다면, 손님은 4쿼터, 2다임, 0니켈, 4페니를 받게 된다.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 거스름돈 C를 나타내는 정수 하나로 이루어져 있다. C의 단위는 센트이다. (1달러 = 100센트) (1<=C<=500)

출력

각 테스트케이스에 대해 필요한 쿼터의 개수, 다임의 개수, 니켈의 개수, 페니의 개수를 공백으로 구분하여 출력한다.

리암이 줘야할 동전 (쿼터, 다임, 니켈, 페니)은 float인것에 비해, 주어지는 거스름돈 C는 정수이고, 달러가 아닌 센트로 주어진다.

문제에서 나와있듯이 1달러는 100센트이기 때문에, 거스름돈 C를 입력받고 이 값에 100으로 나눠서 계산하려고 했다.

근데 나와야 할 예제출력에서 마지막 4가 계속 3으로 찍혔다.

4 2 0 4 3

1 0 0 0

7 1 1 4 3

그래서 중간 중간에 print를 해보니 큰 돈부터 거슬러주다가 0.4가 남아야할 때 0.3999999.. 같은 값이 들어가 있었다.

알고보니 float의 부동소수점 오차 문제였다.

컴퓨터는 2진 분수로 표현하기 때문에 사람이 이해하기 쉬운 10진수를 표현할 때, 비록 정확하지는 않더라도 근사값을 얻어서 보여준다. 이는 해당 숫자에 매우 가깝지만 정확히 동일하지는 않다.

예를 들어 10진수인 0.1을 표현할 때 실제로는 0.1000000000000000055511151231257827021181583404541015625

이지만 이렇게 곧이곧대로 표현하기보다는 파이썬은 10진수 근삿값을 표시한다.

따라서 0.4가 나와야했을 때 0.399999 뭐 대충 이런 값이 뜬 것이다.

해결 방법으로는 애초에 쿼터, 다임, 니켈, 페니를 100을 곱한 값으로 갖고 있던지 (어차피 입력값인 거스름돈도 센트로 입력되기 때문에) 아니면 Decimal을 import해서 사용해주는 방법이 있다.

후자 방법을 사용할 때 주의할 점은 Decimal() 안에 인자를 넣을 때 str 타입을 넣어주어야 한다.

동전값을 처음부터 float이 아닌 int로 받는 방법

T = int(input())

cng =[25,10,5,1]
for _ in range(T):
    C = int(input())

    for i in range(len(cng)):
        num = C // cng[i]
        print(num, end=' ')
        C -= num * cng[i]

    print()

동전값을 float으로 받되 Decimal을 이용해서 부동소수점을 정확하게 표기해주는 방법

from decimal import Decimal

T = int(input())

C = [0.25,0.10,0.05,0.01]

for _ in range(T):
    total = int(input())
    total /=100

    for i in range(len(C)):
        coin = Decimal(str(C[i]))
        change = Decimal(str(total)) // coin
        print(change, end=' ')
        total  = Decimal(str(total)) - change * coin

    print()

위에꺼가 Decimal을 사용한것, 밑에꺼가 int로 계산한 것

profile
Self Refiner

0개의 댓글