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.
>>> (259).to_bytes(2, "big")
>>> (-259).to_bytes(2, "big", signed=True)
>>> (-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.
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"))
# Offset negative ints
if int < 0
int = abs(int) + maxpositive
# Main calculations
output = zeros(UInt8, numbytes)
i = 1
while int != 0
int, output[i] = divrem(int, 256)
i += 1
if byteorder == "big"
julia> @btime _signed_to_bytes(-259, 2, "big")
155.906 ns (9 allocations: 288 bytes)
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 :>
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.
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!
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.
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.