comparison

  • 아래와 같이 a와 b 모두 0.3으로 참이 나와야 하는데 거짓이 나온다.

    1
    2
    3
    4
    5
    a = 0.3
    b = 0.1*3

    a == b
    >> False
  • 이 문제를 해결하기 위한 비교 방법들이다.

  1. 절대 비교 기법(Absolute comparison)

    • 두 수의 차를 절대값으로 만든다.
    • ‘1.0e-10’과 같이 기준을 잡아서 비교하는 것이다.
    • 하지만 ‘1.0e-10’이라는 기준이 너무 막연하고 모호하다.
    • 기준으로 잡는 수를 변경할 수 있도록 매개변수로 잡는 방법도 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      from math import fabs  # math 모듈에서 fabs라는 절대값 함수를 가져옴

      def is_equal_abs(a,b):
      return fabs(a-b) <= 1.0e-10

      if is_equal_abs(a,b):
      print('이 정도 차이면 같다.')
      else:
      print('같은 수가 아니다.')

      >> 이 정도 차이면 같다.
  2. 상대 비교 기법(Relative comparison)

    • sys 모듈에서 epsilon 값을 적용한다.
    • 절대값을 취한 a와 b 사이 중 큰 값을 이용한다.
    • 매개변수를 추가하여 정밀도 범위 조정을 가능하게 한다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      from math import fabs
      import sys

      def is_equal_rel(a,b, w=0):
      """
      is_equal(a, b, w=0) -> bool
      w는 가중치를 의미
      w를 0부터 늘려가며 상대 오차 범위를 조정
      """
      ep = sys.float_info.epsilon # sys 모듈에서 epsilon 값을 적용
      diff = fabs(a-b)

      return diff <= max(fabs(a), fabs(b))*ep*(2**w)


      a = 0.3
      b = 0.3
      if is_equal_rel(a,b):
      print('같다.')
      else:
      print('다르다.')
      >> 같다.
    • 정밀도 범위 조정

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      s = 0.0
      a = 0.01
      t = 1.0

      for _ in range(100):
      s+=a

      # 정밀도 범위를 조정하지 않은 경우
      if is_equal_rel(s, t):
      print('같다.')
      else:
      print('다르다.')

      >> 다르다.


      # 정밀도를 조정한 경우
      if is_equal_rel(s, t, 2):
      print('같다.')
      else:
      print('다르다.')
      >> 같다.
Share