pythonnumpyhalf-precision-float

What makes `print(np.half(500.2))` differs from `print(f"{np.half(500.2)}")`


everyone. I've been learning floating-point truncation errors recently. But I found print(np.half(500.2)) and print(f"{np.half(500.2)}") yield different results. Here are the logs I got in IPython.

In [11]: np.half(500.2)
Out[11]: np.float16(500.2)

In [12]: print(np.half(500.2))
500.2

In [13]: print(f"{np.half(500.2)}")
500.25
  1. I use half.hpp in c++ to compare results with numpy. It seems that 500.2 should be truncated into 500.25 instead of itself.
  2. In binary formats, 500.0 is 0b0_01000_1111010000. So the next float16 number should be 0b_01000_1111010001, which is 500.25 in deximal format.

So what makes print(np.half(500.2)) differs from print(f"{np.half(500.2)}")? Hope to see your answers.


Solution

  • print calls __str__, while an f-string calls __format__. __format__ with an empty format spec is usually equivalent to __str__, but not all types implement it that way, and numpy.half is one of the types that implements different behavior:

    In [1]: import numpy
    
    In [2]: x = numpy.half(500.2)
    
    In [3]: str(x)
    Out[3]: '500.2'
    
    In [4]: format(x, '')
    Out[4]: '500.25'