알고스팟 문제를 풀면서... 질문이 있습니다.

  • 바나나용
    바나나용

    BASEBALL을 풀면서.. WA를 많이 만들었습니다.

    나중에는 아무리봐도 틀린곳이 없는데도 계속 WA를 받아서 한참동안 고민을 했습니다.

    혹시나 해서 cin과 cout을 모두 scanf, printf로 바꿨더니 AC가 뜨던데... 문제푸는데 차이가 있나요??


    9년 전
2개의 댓글이 있습니다.
  • JongMan
    JongMan

    바나나드래곤님의 최근 서브미션들을 보니, WA 에서 AC 로 바뀔 때 사실 두 개의 변화를 적용하셨더군요.

    • 응원하는 팀의 승률을 supportRate 변수에 저장해놨다가 매번 계산하는 것으로 변경
    • cin/cout 을 scanf/printf 로 변경

    무엇이 틀렸는지 알고 싶을 때는 한 번에 한 개씩만 해 보는 게 도움이 됩니다.

    채점 서버로 들어가 테스트를 해 보니 한 개 예제가 답이 다르게 나오더군요. 모든 팀의 승률이 1/3 인 경우였습니다. 그런데 재미있게도 응원하는 팀의 승률이 다른 팀의 승률보다 항상 낮다고 판정되는 문제가 있었습니다. 다음 소스 코드에서요.

    if(getRate(list[i]) > supportRate)
    

    이 줄을

    if(getRate(list[i]) > getRate(list[idx]))
    

    이렇게 고치니 답이 맞게 나옵니다. (자세한건 디스어셈블리 결과를 봐야 알 수 있겠지만) 아마 이 문제의 원인은 아마 컴파일러가 연산 중 80비트 실수형을 사용한 것일 것 같습니다. g++ 은 더 높은 정확도를 위해서 계산 중간에 double 대신에 80비트 실수를 사용하기도 하거든요. getRate() 함수가 인라인되었다고 가정하면, 이 함수의 결과가 80비트로 반환되고, 64비트로 강제로 전환된 supportRate 변수와 비교되면서, 다른 팀의 80비트로 저장된 1/3 이 더 크다는 결론이 내려졌을 거라고 생각됩니다.

    supportRate 를 getRate(list[idx]) 로 바꾸면 답이 맞게 나오는 점도 이 가설로 설명이 되구요.

    그럼 앞으로는

    1. 한번에 한개씩만 바꿔보기
    2. 실수연산을 가능한한 피하시기

    를 바라면서 이만 줄입니다.

    아 이제 일해야지 -_-;;


    9년 전 link
  • 바나나용
    바나나용

    아;; 저런 차이가 있었네요;;

    자세하고 친절한 답변 감사합니다 ^^;;


    9년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.