SmallInteger asByteArray for negative numbers
Hello, I have just found that calling asByteArray for any negative small integer returns the same result that the positive small integer. Is it supposed to be like that or is it a bug? 1 asByteArray = -1 asByteArray. "true" (1 to: 100000) allSatisfy: [ :int | int asByteArray = int negated asByteArray ] âtrue" Cheers, Alejandro
Alejandro,
On 06 Feb 2015, at 15:10, Alejandro Infante <alejandroinfante91@gmail.com> wrote:
Hello, I have just found that calling asByteArray for any negative small integer returns the same result that the positive small integer. Is it supposed to be like that or is it a bug?
1 asByteArray = -1 asByteArray. "true"
(1 to: 100000) allSatisfy: [ :int | int asByteArray = int negated asByteArray ] âtrue"
Cheers, Alejandro
(These kinds of questions should be asked on pharo-users@lists.pharo.org) You can only represent positive numbers as ByteArrays, because to represent negative numbers you have to decide how to do that. The most common solution is to use 2-complement. To do this you also need to decide on the number of bytes to use. Here is an example using 4 bytes: | integer size mask | integer := -123. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) asByteArrayOfSize: 4. => #[255 255 255 133] => FF FF FF 85 The reverse is: | integer size mask | integer := #[255 255 255 133] asInteger. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) negated This is for negative numbers. Positive numbers need not be 2-complemented. When decoding, integers < (2 raisedTo: (size * 8) - 1) are negative. HTH, Sven
On Fri, Feb 6, 2015 at 10:48 PM, Sven Van Caekenberghe <sven@stfx.eu> wrote:
Alejandro,
On 06 Feb 2015, at 15:10, Alejandro Infante < alejandroinfante91@gmail.com> wrote:
Hello, I have just found that calling asByteArray for any negative small integer returns the same result that the positive small integer. Is it supposed to be like that or is it a bug?
1 asByteArray = -1 asByteArray. "true"
(1 to: 100000) allSatisfy: [ :int | int asByteArray = int negated asByteArray ] âtrue"
Cheers, Alejandro
(These kinds of questions should be asked on pharo-users@lists.pharo.org)
You can only represent positive numbers as ByteArrays, because to represent negative numbers you have to decide how to do that. The most common solution is to use 2-complement. To do this you also need to decide on the number of bytes to use.
Here is an example using 4 bytes:
| integer size mask | integer := -123. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) asByteArrayOfSize: 4.
=> #[255 255 255 133]
=> FF FF FF 85
The reverse is:
| integer size mask | integer := #[255 255 255 133] asInteger. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) negated
This is for negative numbers.
Positive numbers need not be 2-complemented.
When decoding, integers < (2 raisedTo: (size * 8) - 1) are negative.
HTH,
Sven
I was going to complain about expecting such niceties as a built in 2s-complement rather than program it myself (I am a bit rusty on such matters), but when I look what should I find? (-123 asTwosComplement: 16rFFFFFFFF) asByteArray. "=> #[255 255 255 133]" cheers -ben
I was going to complain about expecting such niceties as a built in 2s-complement rather than program it myself (I am a bit rusty on such matters), but when I look what should I find?
(-123 asTwosComplement: 16rFFFFFFFF) asByteArray. "=> #[255 255 255 133]"
cheers -ben
Hi Ben, You might want to look at http://www.squeaksource.com/TwosComplement Dave
On 06 Feb 2015, at 18:03, Ben Coman <btc@openInWorld.com> wrote:
On Fri, Feb 6, 2015 at 10:48 PM, Sven Van Caekenberghe <sven@stfx.eu> wrote: Alejandro,
On 06 Feb 2015, at 15:10, Alejandro Infante <alejandroinfante91@gmail.com> wrote:
Hello, I have just found that calling asByteArray for any negative small integer returns the same result that the positive small integer. Is it supposed to be like that or is it a bug?
1 asByteArray = -1 asByteArray. "true"
(1 to: 100000) allSatisfy: [ :int | int asByteArray = int negated asByteArray ] âtrue"
Cheers, Alejandro
(These kinds of questions should be asked on pharo-users@lists.pharo.org)
You can only represent positive numbers as ByteArrays, because to represent negative numbers you have to decide how to do that. The most common solution is to use 2-complement. To do this you also need to decide on the number of bytes to use.
Here is an example using 4 bytes:
| integer size mask | integer := -123. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) asByteArrayOfSize: 4.
=> #[255 255 255 133]
=> FF FF FF 85
The reverse is:
| integer size mask | integer := #[255 255 255 133] asInteger. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) negated
This is for negative numbers.
Positive numbers need not be 2-complemented.
When decoding, integers < (2 raisedTo: (size * 8) - 1) are negative.
HTH,
Sven
I was going to complain about expecting such niceties as a built in 2s-complement rather than program it myself (I am a bit rusty on such matters), but when I look what should I find?
(-123 asTwosComplement: 16rFFFFFFFF) asByteArray. "=> #[255 255 255 133]"
cheers -ben
That is nice indeed, I didn't that existed. Very handy. I don't like that there are no tests ;-)
I would have like to know when I wrote the chapter in deepinto pharo about 2 complement... Stef
(These kinds of questions should be asked on pharo-users@lists.pharo.org)
You can only represent positive numbers as ByteArrays, because to represent negative numbers you have to decide how to do that. The most common solution is to use 2-complement. To do this you also need to decide on the number of bytes to use.
Here is an example using 4 bytes:
| integer size mask | integer := -123. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) asByteArrayOfSize: 4.
=> #[255 255 255 133]
=> FF FF FF 85
The reverse is:
| integer size mask | integer := #[255 255 255 133] asInteger. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) negated
This is for negative numbers.
Positive numbers need not be 2-complemented.
When decoding, integers < (2 raisedTo: (size * 8) - 1) are negative.
HTH,
Sven
I was going to complain about expecting such niceties as a built in 2s-complement rather than program it myself (I am a bit rusty on such matters), but when I look what should I find?
(-123 asTwosComplement: 16rFFFFFFFF) asByteArray. "=> #[255 255 255 133]"
cheers -ben That is nice indeed, I didn't that existed. Very handy.
I don't like that there are no tests ;-)
One more thing: accessing the integer bytes means accessing the details of internal representation... But if you look a bit deeper, you'll discover that: - SmallInteger use 2-complement internally (not accounting for immediate tag bits) - LargeInteger use sign-magnitude internally. So to maintain some uniformity at Integer level, and having all kind of sub-instances behaving identically, we have to cheet. As Sven said, in 2-complement we could model the high bits as an infinite sequence of 1... Not convenient for converting to a finite ByteArray, so we have chosen to behave as if integers were sign-magnitude encoded... Funnily, for bit-ops (bitAnd: bitOr: etc...) we have chosen another paradigm: behave as if integers were 2-complement encoded. 2015-02-06 15:48 GMT+01:00 Sven Van Caekenberghe <sven@stfx.eu>:
Alejandro,
On 06 Feb 2015, at 15:10, Alejandro Infante < alejandroinfante91@gmail.com> wrote:
Hello, I have just found that calling asByteArray for any negative small integer returns the same result that the positive small integer. Is it supposed to be like that or is it a bug?
1 asByteArray = -1 asByteArray. "true"
(1 to: 100000) allSatisfy: [ :int | int asByteArray = int negated asByteArray ] âtrue"
Cheers, Alejandro
(These kinds of questions should be asked on pharo-users@lists.pharo.org)
You can only represent positive numbers as ByteArrays, because to represent negative numbers you have to decide how to do that. The most common solution is to use 2-complement. To do this you also need to decide on the number of bytes to use.
Here is an example using 4 bytes:
| integer size mask | integer := -123. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) asByteArrayOfSize: 4.
=> #[255 255 255 133]
=> FF FF FF 85
The reverse is:
| integer size mask | integer := #[255 255 255 133] asInteger. size := 4. mask := (2 raisedTo: size * 8) - 1. (mask bitAnd: ((integer abs bitXor: mask) + 1)) negated
This is for negative numbers.
Positive numbers need not be 2-complemented.
When decoding, integers < (2 raisedTo: (size * 8) - 1) are negative.
HTH,
Sven
participants (6)
-
Alejandro Infante -
Ben Coman -
David T. Lewis -
Nicolas Cellier -
stepharo -
Sven Van Caekenberghe