furas

Python - floats approximations

Apr 3rd, 2017 (edited)
593
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.36 KB | None | 0 0
  1. # author: Bartlomiej "furas" Burek (https://blog.furas.pl)
  2. # 2017.04.03
  3.  
  4. '''
  5. floats approximations
  6. '''
  7.  
  8. # -----------------------------------------------------------------------------
  9.  
  10. def example_0():
  11.     '''
  12.    floats can keep only aproximations
  13.    and Python can display rounded values which look correctly
  14.    but it uses aproximations in calculations which give incorrect results
  15.  
  16.    0.1 + 0.2 == 0.3  =>  False
  17.  
  18.          0.1  =>  0.1000000000000000055511151231257827021181583404541015625
  19.          0.2  =>  0.2000000000000000111022302462515654042363166809082031250
  20.          0.3  =>  0.2999999999999999888977697537484345957636833190917968750
  21.    0.1 + 0.2  =>  0.3000000000000000444089209850062616169452667236328125000
  22.    '''
  23.  
  24.     print('========== example 0 ==========')
  25.  
  26.     print('0.1 + 0.2 == 0.3', ' => ', 0.1 + 0.2 == 0.3 ) # False
  27.     print()
  28.     print('      0.1', ' => ', '%.55f' % 0.1)
  29.     print('      0.2', ' => ', '%.55f' % 0.2)
  30.     print('      0.3', ' => ', '%.55f' % 0.3)
  31.     print('0.1 + 0.2', ' => ', '%.55f' % (0.1+0.2))
  32.  
  33. # -----------------------------------------------------------------------------
  34.  
  35. def example_1():
  36.     '''
  37.    replace floats with integers to get better results (precision: 100)
  38.    number % divider  ==> ( (number*100) % (divider*100) ) / 100
  39.    '''
  40.  
  41.     print('========== example 1 ==========')
  42.  
  43.     print('1050 % 0.05                        ', ' => ', 1050 % 0.05 )
  44.     print('((1050 * 100) % (0.05 * 100)) / 100', ' => ', ((1050 * 100) % (0.05 * 100)) / 100 )
  45.     print('(105000%5)/100                     ', ' => ', (105000%5)/100 )
  46.  
  47. # -----------------------------------------------------------------------------
  48. # another examples
  49. # -----------------------------------------------------------------------------
  50.  
  51. def example_2():
  52.     '''
  53.    replace floats with integers to get better results (precision: 100)
  54.    number % divider  ==> ( (number*100) % (divider*10) ) / 100
  55.    '''
  56.  
  57.     print('========== example 2 ==========')
  58.  
  59.     for d in [0.3, 0.4, 0.5, 0.6, 0.7, 0.05]:
  60.  
  61.         print('--- x %', d, '---')
  62.         print()
  63.         print('--+-----+-----+-----------------------')
  64.         print('x | int |round| float ')
  65.         print('--+-----+-----+-----------------------')
  66.  
  67.         for x in range(10):
  68.             print( x, '|', ((x*100) % (d*100)) / 100, '|', round(x%d, 1), '|', x%d )
  69.  
  70.         print('--+-----+-----+-----------------------')
  71.         print()
  72.  
  73. # -----------------------------------------------------------------------------
  74.  
  75. def example_3():
  76.     '''
  77.    `math.fmod` - it seems not useful
  78.  
  79.    `numpy` can make opertion on all elements in array
  80.    but it seems it has the same problem with floats
  81.    '''
  82.  
  83.     print()
  84.     print('=== math.fmod ===')
  85.     print()
  86.  
  87.     import math
  88.  
  89.     for d in [0.3, 0.4, 0.5, 0.6, 0.7, 0.05]:
  90.         print('--- x %', d, '---')
  91.         print()
  92.         print('--+-----------------------')
  93.         print('x | fmod ')
  94.         print('--+-----------------------')
  95.  
  96.         for x in range(10):
  97.             print( x, '|', math.fmod(x, d) )
  98.  
  99.         print('--+-----------------------')
  100.         print()
  101.  
  102. # -----------------------------------------------------------------------------
  103.  
  104. def example_4():
  105.     '''
  106.    numpy has float16, float32, float64
  107.    (https://docs.scipy.org/doc/numpy/user/basics.types.html)
  108.    and float32 gives True for 0.1 + 0.2 == 0.3
  109.    but float16 and float64 give False
  110.    '''
  111.  
  112.     import numpy as np
  113.  
  114.     print('========== example 4 - numpy ==========')
  115.  
  116.     print()
  117.     print('--- 0.1 + 0.2 == 0.3 ---')
  118.     print()
  119.  
  120.     a16 = np.float16(0.1) # you can use string np.float16("0.1")
  121.     b16 = np.float16(0.2) # you can use string np.float16("0.2")
  122.     c16 = a16 + b16
  123.     d16 = np.float16(0.3) # you can use string np.float16("0.3")
  124.  
  125.     print('float16:', a16, b16, c16, d16, ' => ', c16 == d16) # 0.1 0.2 0.3 0.3 True
  126.  
  127.     a32 = np.float32(0.1) # you can use string np.float32("0.1")
  128.     b32 = np.float32(0.2) # you can use string np.float32("0.2")
  129.     c32 = a32 + b32
  130.     d32 = np.float32(0.3) # you can use string np.float32("0.3")
  131.  
  132.     print('float32:', a32, b32, c32, d32, ' => ', c32 == d32) # 0.1 0.2 0.3 0.3 True
  133.  
  134.     a64 = np.float64(0.1) # you can use string np.float64("0.1")
  135.     b64 = np.float64(0.2) # you can use string np.float64("0.2")
  136.     c64 = a64 + b64
  137.     d64 = np.float64(0.3) # you can use string np.float64("0.3")
  138.  
  139.     print('float64:', a64, b64, c64, d64, ' => ', c64 == d64) # 0.1 0.2 0.3 0.3 False
  140.  
  141.     print()
  142.     print('--- 1050 % d ---')
  143.     print()
  144.  
  145.     print('int % float16:', 1050 % np.float16(0.05), 'round:', round(1050 % np.float16(0.05), 2)) # 0.00640869140625
  146.     print('int % float32:', 1050 % np.float32(0.05), 'round:', round(1050 % np.float32(0.05), 2)) # 0.0499843545258
  147.     print('int % float64:', 1050 % np.float64(0.05), 'round:', round(1050 % np.float64(0.05), 2)) # 0.0499999999999
  148.     print()
  149.     print('float16 % float16:', np.float16(1050) % np.float16(0.05), 'round:', round(np.float16(1050) % np.float16(0.05), 2)) # 0.0064087
  150.     print('float32 % float32:', np.float32(1050) % np.float32(0.05), 'round:', round(np.float32(1050) % np.float32(0.05), 2)) # 0.0499844
  151.     print('float64 % float64:', np.float64(1050) % np.float64(0.05), 'round:', round(np.float64(1050) % np.float64(0.05), 2)) # 0.0499999999999
  152.  
  153. # -----------------------------------------------------------------------------
  154.  
  155. def example_5():
  156.  
  157.     import numpy as np
  158.  
  159.     for d in [0.3, 0.4, 0.5, 0.6, 0.7, 0.05]:
  160.         print()
  161.  
  162.         for x in range(10):
  163.             print()
  164.             print('---', x, '%', d, '=', ((x*100) % (d*100)) / 100, '---------')
  165.             print('int % f16 |', x % np.float16(d))
  166.             print('int % f32 |', x % np.float32(d))
  167.             print('int % f64 |', x % np.float64(d))
  168.             print('----------+---')
  169.             print('f16 % f16 |', np.float16(x) % np.float16(d))
  170.             print('f32 % f32 |', np.float32(x) % np.float32(d))
  171.             print('f64 % f64 |', np.float64(x) % np.float64(d))
  172.             print('----------+-----------------')
  173.         print()
  174.  
  175. # -----------------------------------------------------------------------------
  176.  
  177. example_0() # 0.1 + 0.2 == 0.3
  178. example_1() # x % 0.05
  179. example_2() # x % 0.05
  180. example_3() # math.fmod()
  181. example_4() # numpy float16/float32/float64
  182. example_5() # numpy float16/float32/float64
Add Comment
Please, Sign In to add comment