>>> import struct
>>> struct.pack('f', 3.141592654)
b'\xdb\x0fI@'
>>> struct.unpack('f', b'\xdb\x0fI@')
(3.1415927410125732,)
>>> struct.pack('4f', 1.0, 2.0, 3.0, 4.0)
'\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@'
Answer from tzot on Stack Overflow
🌐
Finxter
blog.finxter.com › home › learn python blog › 5 best ways to convert python float to bytes
5 Best Ways to Convert Python Float to Bytes - Be on the Right Side of Change
February 16, 2024 - This article provides approaches for converting a Python float, like 3.14, into a bytes representation that is eight bytes long (for a 64-bit float).
Discussions

Confusion about the size of floats in python
In python, everything is an object. That means that getsizeof doesn't just include the raw numerical data, or even a pointer to the raw numerical data, it includes the size of the entire object, including the numerical data, methods, etc. It is what is called an "opaque data type", which means that the exact internal representation is not visible to the user. I am not sure what you mean when you say you are using a "matrix". Python has no built-in multidimensional data structures. Do you mean you are using a numpy matrix or array? If so, the floats in a numpy array are not the same as python floats. In the case of a numpy array, they are true IEEE floats. The array as a whole is an object, but it stores the float data as raw floats in consecutive (or rather strided) regions of memory. So the overhead will only be present once, for the entire array, rather than once for each element of the array (as is the case for Python lists). This means that looking at what happens with an individual python float is not generalizable to a numpy float array. Anyway, the proper data structure for what you are doing is a Pandas DataFrame. You can store this as an HDF5 file so that you don't have to read the whole thing into memory at once. You can also use Dask or Blaze to do true, transparent out-of-core processing. More on reddit.com
🌐 r/learnpython
5
3
June 8, 2015
python - Converting a float to bytearray - Stack Overflow
Is this to display the binary form of the float as hexadecimal text, or to get the raw bytes? Using hex implies you want hexadecimal text, not the raw bytes, and in that case, you wouldn't want a bytearray at all (which is a binary data type), you'd want str (the text type in Python 3). More on stackoverflow.com
🌐 stackoverflow.com
casting - How to interpret 4 bytes as a 32-bit float using Python - Stack Overflow
I am sort of a novice to the Python language and am having a hard time doing something I could very easily do with C++ or Java but for some reason seems so convoluted to do in Python. I have the More on stackoverflow.com
🌐 stackoverflow.com
numpy - How to check the size of a float in python? - Stack Overflow
Properties of a Python float can be requested via sys.float_info. It returns information such as max/min value, max/min exp value, etc. These properties can potentially be used to calculate the byte size of a float. More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com › r/learnpython › confusion about the size of floats in python
r/learnpython on Reddit: Confusion about the size of floats in python
June 8, 2015 -

Hi, not sure if this belongs here or in the main python sub, but decided to try here first. Anyways, I'm working on a project where I have a large text file which essentially contains a roughly 22,000x6,000 matrix of decimal values. This file is >2GB in size, however it's all encoded as text so the size of the data should become considerably smaller once I read them in and represent them as floats (they are mostly a single-digit integer part with 14 digit fractional part, along with the decimal point itself, each character of which UTF-8 can represent as a single byte since it's in the ascii range so each value should use 16 bytes if my calculations are correct). I figure that python represents floats as 8-byte double precision values, as the documentation says CPython will use a C double for your platform to represent them. My googling seems to support this assumption. That would mean that my original matrix in the file should be about 16220006000 ~= 2 GB (not including the whitespace separators), and the matrix in memory as floats should be 8220006000 ~= 1 GB, which while not small, should fit comfortably in memory on my laptop. However, this is not the case and I'm getting an out of memory error as a result.

As a result, I did some investigation and did >>> x = 3.14 >>> sys.getsizeof(x) 24 What the hell, how can this be??? What could CPython possibly be doing with 24 bytes? All I can figure is that there's an 8-byte pointer to a 16-byte double (huge!) and getsizeof() is counting both? Note that this is 64-bit CPython running on linux. I tried again on a 32-bit CPython running on windows and the answer I got was 16 bytes, so I figure this means a 4-byte pointer to an 8-byte double? Somewhat frustrated with this result, I tried again, this time using numpy.float16 because these are relatively small values and I don't need all that space anyways. For the linux 64-bit CPython I got 24 bytes again, and on the Windows 32-bit CPython I got 12 bytes. No idea at all what's happening here because if my previous guesses were correct I should have 8 and 4 byte pointers to 2-byte float16s, giving 10 and 6 bytes, respectively. Clearly I'm missing something here. Can anyone explain what's happening to me, and why so much memory is being used to store these values?

Also, I'm aware that my use case is memory intensive and I'm working on refactoring so that I don't need to have everything in memory at once. However, I'm still extremely curious about this behavior as it seems strange to me. Thanks!

Top answer
1 of 3
5
In python, everything is an object. That means that getsizeof doesn't just include the raw numerical data, or even a pointer to the raw numerical data, it includes the size of the entire object, including the numerical data, methods, etc. It is what is called an "opaque data type", which means that the exact internal representation is not visible to the user. I am not sure what you mean when you say you are using a "matrix". Python has no built-in multidimensional data structures. Do you mean you are using a numpy matrix or array? If so, the floats in a numpy array are not the same as python floats. In the case of a numpy array, they are true IEEE floats. The array as a whole is an object, but it stores the float data as raw floats in consecutive (or rather strided) regions of memory. So the overhead will only be present once, for the entire array, rather than once for each element of the array (as is the case for Python lists). This means that looking at what happens with an individual python float is not generalizable to a numpy float array. Anyway, the proper data structure for what you are doing is a Pandas DataFrame. You can store this as an HDF5 file so that you don't have to read the whole thing into memory at once. You can also use Dask or Blaze to do true, transparent out-of-core processing.
2 of 3
3
In CPython, every object begins with a reference count (of type ssize_t, i.e. a machine word) and a pointer to the type object for that object, which is necessary to be able to do any operations (e.g. invoke a method) on the object. That's two machine words right there off the bat, before you even start to talk about the data contained in the object. After that header comes a variable amount of data; in the case of a float object, it's just a C double value directly, so another eight bytes. For a 32 bit CPython, that's 4 + 4 + 8 = 16 bytes, for a 64 bit CPython, that's 8 + 8 + 8 = 24 bytes. Note that CPython can also be configured for debug builds, which adds two more pointers to that common header shared by all objects, which are used to form a doubly linked list of all objects on the heap, which can be used to track down reference counting bugs. Modules like Numpy can store raw values without these object headers, but that representation is completely hidden from you. Anything that you can actually access has to be an object. So while the values inside that Numpy array may only occupy 2 bytes each, the moment that you access any such value, it's converted (boxed) into a Python object that has the same header as any other object in Python. It's impossible not to see the contribution of that header using sys.getsizeof(), because you can't not pass a Python object to that function. Moreover, these structures are subject to alignment requirements. At the very least, each member of the structure must have its natural alignment (e.g. a member that's 4 bytes must be aligned to the nearest 4 byte boundary, a member that's 8 bytes must be aligned to the nearest 8 byte boundary, and so on.) That also means that the overall size of the structure must be padded to accommodate the member with the highest alignment, so for example if a struct contains an 8 byte pointer, then the size of the struct must be a multiple of 8; extra padding will be inserted at the end to make that happen. If that wasn't the case, then you couldn't pack structures back to back and still satisfy the alignment requirements of each individual member. Since the Python object header contains two machine words, that means its size must be a multiple of the native word size. In your example of a numpy.float16 object, on a 64 bit system, the layout would be 8 + 8 + 2 + 6 bytes padding = 24. And on a 32 bit system, 4 + 4 + 2 + 2 bytes padding = 12 bytes. But again, this only applies when you actually access these values as Python objects, but the whole point of Numpy is to avoid doing that. When you declare an ndarray in Numpy, all the values are packed without Python object headers, and are accessed by C in their raw form. If you multiply a Numpy array by a scalar for instance, that's all done in C without any boxing or unboxing. But if you write e.g. my_numpy_float12_array[42] then Numpy has to extract that value from its compact 2 byte representation and box in a Python object, resulting in a 24 byte Python object on a 64 bit system. It's impossible to access that 2 byte value directly, because you can only access Python objects. But as long as you use Numpy properly, that's not a problem, because you're rarely accessing individual elements like that. Again, the whole point of Numpy is to avoid doing as much as possible in Python and do everything in C, i.e. you should never manually loop over values, you should use whatever vector construct represents the operation you're trying to perform.
🌐
GeeksforGeeks
geeksforgeeks.org › python › how-to-convert-binary-data-to-float-in-python
How to Convert Binary Data to Float in Python? - GeeksforGeeks
July 23, 2025 - ... Input: b'\x40\x49\x0f\xdb' <class 'bytes'> Output: 3.1415927410125732 <class 'float'> Explanation: Here, we have binary data b'\x40\x49\x0f\xdb' those we converted into float 3.1415927410125732.
Find elsewhere
🌐
Read the Docs
python.readthedocs.io › en › latest › library › stdtypes.html
4. Built-in Types - Python 3.7.0a2 documentation
November 15, 2017 - Floating-point numbers are usually implemented using double in C; information about the precision and internal representation of floating-point numbers for the machine on which your program is running is available in sys.float_info. Complex numbers have a real and imaginary part, which are each a floating-point number.
🌐
Finxter
blog.finxter.com › home › learn python blog › convert bytes to floating point numbers
Convert Bytes To Floating Point Numbers - Be on the Right Side of Change
March 24, 2022 - The struct module has three methods: pack(), unpack(), and calcsize(). The pack method accepts two parameters: format and data to be converted to bytes. Like the struct blueprint in C, the format part of the pack function in Python accepts various data types. For example, ... This means converting integer 2, integer 4 and float 7.68 to a stream of bytes.
🌐
Reddit
reddit.com › r/learnpython › byte representation of float?
r/learnpython on Reddit: Byte representation of float?
July 13, 2018 -

Hi all,

I'm working on an application where I need to send some time data over CAN. I have no issues doing simple bitwise manipulation to get hours and minutes into byte form, but I am having a hard time trying to figure out how to get fractional seconds into byte form. Specifically, I need to send the data with 13bits of precision.

I've seen some documentation on how to do this math wise, but I'm curious if there's a way to do this easily in Python.

Any thoughts?

🌐
Pycom User Forum
forum.pycom.io › home › getting started › lopy › converting float to bytes
Converting float to bytes | Pycom user forum
June 11, 2018 - and using 'e' instead of 'f' for the format will mean the float uses 4 bytes in hex form.
🌐
Python
docs.python.org › 3 › library › struct.html
struct — Interpret bytes as packed binary data
February 23, 2026 - The 'n' and 'N' conversion codes are only available for the native size (selected as the default or with the '@' byte order character). For the standard size, you can use whichever of the other integer formats fits your application. For the 'f', 'd' and 'e' conversion codes, the packed representation uses the IEEE 754 binary32, binary64 or binary16 format (for 'f', 'd' or 'e' respectively), regardless of the floating-point format used by the platform.
🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › programming › python
Conversion float to byte and backward - Python
from ctypes import * import array import struct import binascii class ieeef(Structure): _fields_ = [ ("fdata",c_float)] class calf(Union): _fields_ = [("data", ieeef), ("hdata",c_ubyte *4 )] def str2barray(S): try: return bytearray.fromhex(S) except ValueError: return None def barray2str(B): return binascii.b2a_hex(B) def ieee2ccs(d): #c_ubyte_Array #ieee754 bytearray to ccs(microchip float) j = bytearray(d) sb=j[3]&128 lse=j[2]&128 j[3]&=127 j[3]<<=1 if lse : j[3]+=1 if sb: j[2]|=128 else: j[2]&=127 return j def ccs2ieee(j): #bytearray(d) #ieee754 bytearray ccs(microchip float) to ieee74 byte
🌐
Finxter
blog.finxter.com › home › learn python blog › 5 best ways to convert python list of bytes to float
5 Best Ways to Convert Python List of Bytes to Float - Be on the Right Side of Change
February 27, 2024 - In this snippet, the list of bytes is first converted into an integer using int.from_bytes. This integer is then converted back to bytes and finally unpacked into a float using the struct module, similar to Method 1. Python’s bytearray and memory views allow for the in-place manipulation of byte data.
Top answer
1 of 4
1

Finally, I have also found this message by Ehud Karni on the mailing list. Indeed that code also gives you the correct numbers in hexadecimal. I will paste it here (it does not work when directly copy pasting from the mailing list message)

(defvar IEEE-sign-mlt 128 "multiplier for sign")                       ;  1 bits
(defvar IEEE-exp-bias 127 "exponent bias for float")                    ;  8 bits
(defvar IEEE-mantissa-divisor ?\x800000 "mantissa divisor for float")  ; 23 bits
(defvar IEEE-float-mantissa-divisor (/ 1.0 (float IEEE-mantissa-divisor))
  "floated 1 / mantissa divisor")


(defun IEEE-float-2-hex (FNUM)
  "Convert a floating point number FNUM to 8 Hex digits string (big endian)"
  (interactive "nEnter float to convert: ")
  (or (floatp FNUM)
      (setq FNUM (float FNUM)))
  (let ((IEEE-sign 0)
        (IEEE-exp  0)
        (IEEE-mantissa 0)
        hex)
    (and (< FNUM 0)                         ; negative
         (setq IEEE-sign IEEE-sign-mlt)      ; yes, sign=1 (* 2**7)
         (setq FNUM (- FNUM)))               ; negate (abs) it
    (cond
     ((= FNUM 0))                        ; Zero - we all set
     ((= FNUM 1e+INF)                    ; infinite ?
      (setq IEEE-exp IEEE-exp-bias))  ; exp = max, mantissa = 0

     (t                                  ;; real float
      (setq IEEE-exp (floor (log FNUM 2.0)))      ; exponent [ log 2 FNUM ] - integer
     (if (<= IEEE-exp (- IEEE-exp-bias))         ; check for De-normalized number
         (setq IEEE-exp 0                        ; really - 
           IEEE-exp-bias
               IEEE-mantissa (truncate (* IEEE-mantissa-divisor
                      0.5 FNUM (expt 2.0 IEEE-exp-bias))))
         ;; normal float
         (setq IEEE-mantissa (truncate (* IEEE-mantissa-divisor
                      (- (/ FNUM (expt 2.0 IEEE-exp)) 1))))
         (setq IEEE-exp (+ IEEE-exp IEEE-exp-bias))) ;; offset-ed exp
     ))
  (setq hex (format "%02X%06X" (+ IEEE-sign (/ IEEE-exp 2))
                    (+ IEEE-mantissa
                       (* (% IEEE-exp 2) 
              IEEE-mantissa-divisor))))

  ;;         (message "Float=%f sign=%d, exp=%d, mant=%d  HEX=%s"
  ;;                  FNUM IEEE-sign IEEE-exp IEEE-mantissa hex)

  (print hex)))

(defun IEEE-hex-2-float (HEX)
  "Convert an 8 Hex digits string (big endian) to floating point number"
  (interactive "sEnter hex value (8 hex digits): ")
  (if (or (not (stringp HEX))
          (/= (length HEX) 8)
          (string-match "[^0-9a-fA-F]" HEX))
      (error "Arg must be a string of EXACTLY 8 hex (1-8, a-f, A-F) 
digits"))

  (let ((S-EXP (string-to-number (substring HEX 0 2) 16))
        (MANTISSA (string-to-number (substring HEX 2) 16))
        (RSLT 1)
        IEEE-sign
        IEEE-exp
        IEEE-mantissa
        )
    (setq IEEE-mantissa (logior MANTISSA IEEE-mantissa-divisor)) ; always set upper bit
    (if (= IEEE-mantissa IEEE-mantissa-divisor)             ; = --> zero mantissa, check special cases
        (cond
         ((string-equal HEX "00000000")
          (setq RSLT (float 0)))      ; Zero
         ((string-equal HEX "3F800000")
          (setq RSLT  1e+INF))        ; + infinity
         ((string-equal HEX "BF800000")
          (setq RSLT -1e+INF))        ; - infinity
         ))
    (print (if (/= RSLT 1)
               RSLT                                            ; special cases (0, infinity)

         (setq IEEE-sign (ash S-EXP -7))                     ; shift right 7 bits
         (setq IEEE-exp (+ (ash (% S-EXP IEEE-sign-mlt) 1)   ; shift (part) exp 1
                               (ash MANTISSA -23)))              ; 1 bit from mantissa
         (if (= IEEE-exp 0)                                  ; De-normalized ?
         (setq IEEE-mantissa (ash
                      (logxor IEEE-mantissa IEEE-mantissa-divisor) 1))) ; clear upper bit
         ;;             (message "Hex=%s sign=%d, exp=%d, mant=%d"
         ;;                      HEX IEEE-sign IEEE-exp IEEE-mantissa)

         (*                                                  ; result float
          (- 1 IEEE-sign IEEE-sign)                       ; sign
          (expt 2.0 (- IEEE-exp IEEE-exp-bias))           ; 2 ** exponent (un-biased)
          (float IEEE-mantissa)                           ; mantissa part
          IEEE-float-mantissa-divisor                     ; 1 / mantissa divisor
          )))))

You will get the bytes in hexadecimal representation as a string. Unfortunately I don't know how to 'convert' those strings to hexadecimal numbers (starting with #x), but if you find a way to convert the hexadecimal strings to numbers, then you could use this solution also.

2 of 4
2

You can't. Emacs Lisp is a highly abstract, strongly typed dynamic language where everything is a reference. It determines the data type through the highest bits of pointers in C language. If you want to treat a floating point number as an integer, you have to modify some bits of the pointer. This can't be done in Emacs Lisp; you must modify it through a debugger like GDB.

But you can write a function to find out the precise representation of a floating point number. As per the elisp manual, Emacs Lisp follows IEEE-754.

🌐
Projectpython
projectpython.net › chapter02
ProjPython – Variables and expressions - Project Python
The floating-point type (or “float type” for short) is used for numbers that have fractional parts or are too large to store in a long int that takes up a reasonable amount of memory. Typically, eight bytes are used for the Python floating type. Notice that this means that there are only ...
🌐
Finxter
blog.finxter.com › converting-python-bytes-to-float-top-5-effective-methods
Converting Python Bytes to Float: Top 5 Effective Methods – Be on the Right Side of Change
February 23, 2024 - import struct bytes_data = bytearray(b'\x40\x49\x0f\xdb') float_value = struct.unpack('d', memoryview(bytes_data))[0] print(float_value) ... The above example creates a memoryview on the bytearray which can then be passed to struct.unpack. This can be memory efficient as it avoids creating an intermediate bytes object when dealing with large binary data. This method is theoretically sound but doesn’t actually exist in Python’s standard library.