1

I need a function to convert a float number to a fixed-point number, represented in binary so that I can put it to the hardware accelerator which can only accept fix-point number. for example, when I input a float number 5.625, giving data width 8, precision 4(4 bits for mantissa), it will return b'01011010, or h'5a or d'90. Is there any functions like this in python libraries?

bander zhang
  • 21
  • 1
  • 3

5 Answers5

4

That's the same as multiplying by 16 and converting to an int.

>>> int(5.625 * (2 ** 4))
90

The 16 depends on the number of bits in the precision, but it's easily calculated.

If the number has to go in multiple bytes (like 2 or 4), use the struct module. E.g. for 300.625 with 32 data bits, 8 of which are precision:

>>> int(300.625 * (2**8))
76960
>>> struct.pack('I', 76960)  # 'I' is 4-byte unsigned int
b'\xaa,\x01\x00'
RemcoGerlich
  • 30,470
  • 6
  • 61
  • 79
  • On this site, show your appreciation by upvoting all the useful answers. You do that by clicking the up-arrow at the top-left of the answer. In addition, accept the best answer (if it actually answers your question) by clicking the checkmark near the top-left of the answer. That is better than saying thanks in a comment. It also helps others to see that your question was answered. – Rory Daulton Jan 11 '17 at 13:02
1

You can use fxpmath in python. You can find info about it at:

https://github.com/francof2a/fxpmath

In your example case:

from fxpmath import Fxp

x = Fxp(5.625, signed=False, n_word=8, n_frac=4)
print(x)         # float value
print(x.bin())   # binary representation
print(x.hex())   # hex repr
print(x.val)     # raw val (decimal of binary stored)

Outputs:

5.625
01011010
0x5a
90

francof2a
  • 154
  • 4
1

several fixed point libraries like numfi can transform floating point number to fixed point and give bin/dec/hex representation

>>> from numfi import numfi
>>> x = numfi(5.625,1,8,4)
>>> x.int # d'90
array([90], dtype=int64)
>>> x.bin # b'01011010
array(['01011010'], dtype='<U8')
>>> x.hex # h'5a
array(['5A'], dtype='<U2')

If you prefer simpler solution, you can do quantization yourself:

num = 5.625
w = 8 # data width
f = 4 # fraction width
quantized = np.round(num*(2**f)).astype(int) #note: overflow is not considered here
dec_repr = np.base_repr(quantized, base=10)
bin_repr = np.binary_repr(quantized, width=8)
hex_repr = np.base_repr(quantized, base=16)
0

Try to use decimal module.

You may pass it a float formatted as a string with required format and precision:

>>> from decimal import Decimal

>>> '{:5f}'.format(10.0)
'10.000000'

>>> Decimal('{:5f}'.format(10.0))
Decimal('10.000000')
Eugene Lisitsky
  • 12,113
  • 5
  • 38
  • 59
0
def float2fix(val, width, precision):
    integer = abs(int(val * 2 ** precision))
    if val < 0:
        integer = 2 ** (width-1) - integer
    if val >= 0:
        fix_str = bin(integer).replace('0b', '').rjust(width, '0')
    else:
        fix_str = '1'+bin(integer).replace('0b', '').rjust(width-1, '0')
    return fix_str
bander zhang
  • 21
  • 1
  • 3