Hello,

The conversion of -1 to binary or hexadecimal is returning -1, is this normal?

val = -1

val.to_s(2) or val.to_s(16) is returning -1, while everywhere I look they use the 2-complement (for instance -1 in the windows calc gives FFFF FFFF FFFF FFFF)

Ruby also gives `-1`

. I think `FFFF FFFF FFFF FFFF`

meaning both -1 and 18446744073709551615 is confusing. I guess that if you want negative numbers to be converted like that you can do it yourself. The question is: how many "F"s do you want? Of course it depends on the type… but again, I think it’s not clear that `-1`

should be `FFFF FFFF FFFF FFFF`

because it’s not bijective: if you want to go back to the original value from that you have no idea which value was it.

1 Like

base 16 and binary representation are different things.

https://crystal-lang.org/api/0.30.1/IO/ByteFormat.html might help if you want to deal with the later.

Personally I think it is a bit strange that (-1).to_s(2) does not give the binary representation of -1 but if Ruby is doing the same then it is better to stick with this.

For how many ‘F’ I want, it would depend on the type of -1 (int32 or int64 for instance).

I can get what I want by doing this: (0_u32 -1).to_s(16), but it would be better to have something that works for any integer type.

You’re actually mixing up two completely different concepts.

A **binary number** is just a number expressed in base-2 notation. Apart from the digits, everything else is exactly the same as in other number systems like decimal or hexadecimal. For example, negative numbers are obviously prefixed by a minus sign.

The decimal number `-1`

expressed as binary number is also just `-1`

. The hexadecimal value `FFFF FFFF FFFF FFFF`

is just a simple number, equivalent to decimal `18446744073709551615`

.

These conversions are all handled by `.parse`

and `#to_s`

methods on Crystal’s number types.

When you expect `FFFF FFFF FFFF FFFF`

to mean `-1`

, you’re actually talking about a **integer data type** representation which uses the two’s complement to encode a signed number. This is just a specific data format used to represent arbitrary values (in this case: a signed integer) as binary data.

This encoding is usually handled by Crystal internally and you don’t actually see it, but it can be explicitly used with the `IO::ByteFormat`

type.

2 Likes