5

Probably a stupid question but I stumbled across the int.to_bytes() function and I can't explain why I have to add "+7" if I calculate the bytes length and there is no hint in the documentation. I am sure I miss some bit/byte calculation magic but I need a little help from the community here.

Example what confused me: x.to_bytes((x.bit_length() + 7) // 8, byteorder='little') from https://docs.python.org/3/library/stdtypes.html#int.to_bytes

Thanks in advance

4
  • 4
    There are 8 bits in a byte. The +7 is just a cheesy way of making sure that the // 8 is rounded up to the nearest whole byte. Commented Oct 23, 2020 at 14:46
  • @Samwise - that makes sense. I ran x=10; x.bit_length() on the python shell on python.org and got 4. Makes sense that you would need to round to the nearest whole byte. Commented Oct 23, 2020 at 14:47
  • Another way to do it might be x.to_bytes(math.ceil((x+1)/256), 'little'). Feels a little more straightforward to me to just divide by the int value of a full byte and use math.ceil than to use bit_length and do shenanigans with the number of bits. Commented Oct 23, 2020 at 14:50
  • @Samwise Ok, now I get it. I didn't think about that // is not the "true" division but the floor division. Now it makes sense for me. For everyone didn't know the difference between true and floor division: docs.python.org/3/whatsnew/… Commented Nov 2, 2020 at 8:51

1 Answer 1

4

bit_length returns the number of bits necessary to represent an integer in binary, excluding the sign and leading zeros. So

(x.bit_length() + 7) // 8 

will just give you the number of bytes necessary to represent that integer x. You could also write something like

from math import ceil ceil(x.bit_length() / 8) 

to get the same number.

The method to_bytes() requires this byte length as its first argument.

To account for x == 0, use the max function to ensure that the number of bytes is at least one:

x.to_bytes(length=(max(x.bit_length(), 1) + 7) // 8, byteorder='little') 
Sign up to request clarification or add additional context in comments.

1 Comment

@Simon Fromme Thanks for the explanation but the missing link for me was that the // cuts off everything behind the point.