# Julia equivalent to Python's int.to\_bytes

**URL:** <https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038>\
**Category:** General Usage\
**Tags:** question, python\
**Created:** [July 31, 2020, 2:30pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038 "2020-07-31T14:30:40Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 2:30pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/1 "2020-07-31T14:30:40Z")

</div>

Hi everyone :\>  
I’ve been using Julia the past few days, and so far I’ve been enjoying it. I’ve been trying to replicate Python functionality as a little exercise in Julia, but now I’m getting stuck on Python’s `int.to_bytes` function. I tried to read through the CPython source file `longobject.c`, but I can’t really read too much C yet.

Example:

```julia
>>> (259).to_bytes(2, "big")
b'\x01\x03'
>>> (-259).to_bytes(2, "big", signed=True)
b'\xfe\xfd'
>>> (-259).to_bytes(2, "big", signed=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: can't convert negative int to unsigned

```

I attempted to replicate it as follows, but this feels inelegant. It’s also _wrong_ for any numbers smaller than -128. Are there any built-in functions one could use to make this more readable and maybe faster?

I’m rather worried at that `^` call as well, it could result in weird behavior when it grows too large. I don’t really know how to replicate that behavior with `log`.

```julia
function _signed_to_bytes(int::Integer, numbytes::Integer, byteorder::AbstractString)
    maxpositive = (256 ^ numbytes) / 2 - 1
    maxnegative = -(maxpositive + 1)
    # Bounds check
    if !(maxnegative <= int <= maxpositive)
        throw(OverflowError("Cannot represent signed int $int with $numbytes bytes"))
    end
    # Offset negative ints
    if int < 0
        int = abs(int) + maxpositive
    end
    # Main calculations
    output = zeros(UInt8, numbytes)
    i = 1
    while int != 0
        int, output[i] = divrem(int, 256)
        i += 1
    end
    if byteorder == "big"
        reverse!(output)
    end
    return output
end

julia> @btime _signed_to_bytes(-259, 2, "big")
  155.906 ns (9 allocations: 288 bytes)
2-element Array{UInt8,1}:
 0x81
 0x02

```

---

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 2:34pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/2 "2020-07-31T14:34:52Z")

</div>

I’ve at least figured out why it was wrong for negative numbers. When the number is negative, I’m supposed to count backwards from the maximum value rather than offset it forward.

Like, `0xff` is -1, `0xfe` is -2 and so on, not `0x80` is -1 and `0x81` is -2.  
My bad.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 2:51pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/3 "2020-07-31T14:51:18Z")

</div>

> [@louie4825](#):
>
> I’ve been trying to replicate Python functionality as a little exercise in Julia, but now I’m getting stuck on Python’s `int.to_bytes`

```julia
julia> to_bytes(x) = reinterpret(UInt8, [x])
to_bytes (generic function with 1 method)

julia> to_bytes(3)
8-element reinterpret(UInt8, ::Array{Int64,1}):
 0x03
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00

```

This uses the native byte order, which is littlendian on most machines these days. If you want bigendian order, call `hton`:

```julia
julia> to_bytes(hton(3))
8-element reinterpret(UInt8, ::Array{Int64,1}):
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x03

```

This will only work on machine integers, not `BigInt` (which is stored via a pointer to some other data structure, so you won’t get the bytes of the actual numbers).

You could also use `digits`:

```julia
julia> digits(UInt8, 3, base=256)
1-element Array{UInt8,1}:
 0x03

julia> digits(UInt8, 3, base=256)
1-element Array{UInt8,1}:
 0x03

julia> digits(UInt8, 3, base=256, pad=sizeof(3))
8-element Array{UInt8,1}:
 0x03
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00

```

but asking for `UInt8` bytes via `digits` doesn’t work for negative values.

---

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 2:54pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/4 "2020-07-31T14:54:19Z")

</div>

Thanks for the answer. That’s _almost_, like really close to what I’m trying to do. However, in Python, I can specify the number of bytes that the number is represented in, and the representation follows. Is there any way to specify that, the number of bytes to represent it with, as of yet?

If not, a little guidance on how to accomplish this would be greatly appreciated :\>

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 2:56pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/5 "2020-07-31T14:56:43Z")

</div>

> [@louie4825](#):
>
> Is there any way to specify that, the number of bytes to represent it with, as of yet?

Cast the value to `Int8`, `Int16`, `Int32`, `Int64`, or `Int128` — unlike Python, Julia actually has integer types of various widths.

```julia
julia> to_bytes(Int16(3))
2-element reinterpret(UInt8, ::Array{Int16,1}):
 0x03
 0x00

```

What do you need this function for, anyway?

---

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 3:01pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/6 "2020-07-31T15:01:01Z")

</div>

Thanks. I think I can get that to work now. Just one more question

How about for values which do not fall in the range of `Int8`, `Int16`, …, such as 3 bytes or a sort-of `Int24`? It’s probably,_very probably_, useless, but I want to see how accurate I can make it.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 31, 2020, 3:04pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/7 "2020-07-31T15:04:30Z")

</div>

> [@louie4825](#):
>
> That’s _almost_ , like really close to what I’m trying to do.

Is this representation really the goal, or do you need it as part of a solution to a problem? If the latter, maybe some context would be helpful. Eg if you are trying to serialize/deserialize values, see the standard library Serialization.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 3:05pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/8 "2020-07-31T15:05:59Z")

</div>

> [@Tamas\_Papp](#):
>
> if you are trying to serialize/deserialize values, see the standard library Serialization.

Or just use `write` and `read`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 31, 2020, 3:08pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/9 "2020-07-31T15:08:57Z")

</div>

I don’t think that would work for `BigInt`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 3:13pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/10 "2020-07-31T15:13:07Z")

</div>

> [@louie4825](#):
>
> How about for values which do not fall in the range of `Int8` , `Int16` , …, such as 3 bytes or a sort-of `Int24` ? It’s probably, _very probably_ , useless, but I want to see how accurate I can make it.

Here is a more general replacement for Python’s `to_bytes` function, mainly as a learning exercise. The trick is to use bit shift (`>>`) and mask (`&`) operations:

```julia
julia> function to_bytes(n::Integer; bigendian=true, len=sizeof(n))
           bytes = Array{UInt8}(undef, len)
           for byte in (bigendian ? (1:len) : reverse(1:len))
               bytes[byte] = n & 0xff
               n >>= 8
           end
           return bytes
       end
to_bytes (generic function with 3 methods)

julia> to_bytes(-28, len=7)
7-element Array{UInt8,1}:
 0xe4
 0xff
 0xff
 0xff
 0xff
 0xff
 0xff

julia> to_bytes(2345, len=7)
7-element Array{UInt8,1}:
 0x29
 0x09
 0x00
 0x00
 0x00
 0x00
 0x00

julia> to_bytes(2345, len=7, bigendian=false)
7-element Array{UInt8,1}:
 0x00
 0x00
 0x00
 0x00
 0x00
 0x09
 0x29

```

However, it’s not clear to me what this function is actually useful for — Julia has much better alternatives for most things that you might want this for (serialization, bit manipulations, etcetera).

---

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 3:14pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/11 "2020-07-31T15:14:58Z")

</div>

Oh. That’s so clean. That’s what I’m looking for. I really only meant for this as a learning exercise, so it’s about as useful as Python’s own `to_bytes` function. I’ll look into the alternatives you mentioned for when I need them later on. They seem quite useful. Thanks for all the help!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 3:16pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/12 "2020-07-31T15:16:04Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t think that would work for `BigInt` .

Correct, `write` doesn’t have a method for `BigInt`. That’s because for `BigInt` you’d have to decide on a format beyond just bytes for the digits, since it has a variable width that you’d need to serialize as well. Either Julia’s native `serialize` format or some other format of your choice.

---

<div class="post-metadata">

**Author:** ![louie4825](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/louie4825/32/27359_2.png) [@louie4825](https://discourse.julialang.org/u/louie4825)\
**Post date:** [July 31, 2020, 3:53pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/13 "2020-07-31T15:53:28Z")

</div>

> [@stevengj](#):
>
> Here is a more general replacement for Python’s `to_bytes` function, mainly as a learning exercise. The trick is to use bit shift ( `>>` ) and mask ( `&` ) operations:

By the way, @stevengj, is it okay to incorporate this into the code? I’m planning to release this as an open source package sometime, and I’d like your prior permission to avoid any issues down the line.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 31, 2020, 5:00pm UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/14 "2020-07-31T17:00:36Z")

</div>

> [@louie4825](#):
>
> By the way, @stevengj, is it okay to incorporate this into the code? I’m planning to release this as an open source package sometime, and I’d like your prior permission to avoid any issues down the line.

Yes. All code posted to discourse is automatically MIT-licensed, as described in the Terms of Service: [Terms of Service - Julia Programming Language](https://discourse.julialang.org/tos)

---

<div class="post-metadata">

**Author:** ![valeriu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/valeriu/32/18324_2.png) [@valeriu](https://discourse.julialang.org/u/valeriu)\
**Post date:** [October 1, 2020, 11:56am UTC](https://discourse.julialang.org/t/julia-equivalent-to-pythons-int-to-bytes/44038/15 "2020-10-01T11:56:08Z")

</div>

I needed a similar function for calling `crc32(data::Vector{UInt8})`, from [Libz.jl](https://github.com/BioJulia/Libz.jl/blob/master/src/checksums.jl).
