I am a bit confused by the Oct
function. Oct(-8)
does not return -10, it returns 37777777770. I will just write my own function but does anyone know why it gives such a weird result back?
-
This is not specific to .NET, MS Calc gives the same output. – Matt Wilko Aug 14 '15 at 15:18
-
2This is because its the [*Two's Complement*](http://stackoverflow.com/questions/1049722/what-is-2s-complement) representation of the negative number. ((bits flipped)+1) – Alex K. Aug 14 '15 at 15:25
-
Same as the Hex() function. Dates from earlier VB versions that did not yet support unsigned integers. Displaying the binary representation of a value would not have been simple otherwise. You'd only ever appreciate Oct() if you used DEC operating systems before. – Hans Passant Aug 14 '15 at 15:32
-
_"did not yet support unsigned integers"_ blimey... – James Thorpe Aug 14 '15 at 15:34
1 Answers
How do computers represent negative numbers in binary anyway?
Throughout the years several ways have been dreamed up for representing negative numbers, but for the sake of keeping this answer on the short side of a dissertation we're only going to look at two's complement.1
To calculate a negative number's two's complement, we use the following steps:
- Take the magnitude of the number (aka. it's absolute value)
- Complement all the bits (Bitwise Not)
- Add 1 to the result (Simple addition)
So what's -8 in two's complement binary? First let's convert the absolute value to binary (For now we'll work in 8 bit for simplicity. I've worked out the same answer below with 32 bit numbers.)
|8| => 0000 1000
The next step is to complement all of the bits in the number
0000 1000 => 1111 0111
Finally we add 1 to the result to get our two's complement representation
1111 0111
+ 1
----------
1111 1000 (Don't forget to carry)
Ok, a brief review of octal numbers. Octal, or base 8, is another way of representing binary numbers in a more compact way. The more observant will notice that 8 is a power of 2 and we can certainly use that fact to our advantage converting our negative number to octal.
Why does this make Oct
produce weird results with negative numbers?
The Oct
function operates on the binary representation of the number, converting it to it's octal (Base 8) representation. So let's convert our 8 bit number to octal.
1111 1000 => 11 111 000 => 011 111 000 => 370
Note that since 8 = 2^3
it's easy to convert, because all we have to do is break the number up into groups of three bits and convert each group. (Much like how hex can be converted by breaking into groups of 4 bits.)
So how do I get Oct
to produce a regular result?
Convert the absolute value of the number to octal using Oct
. If the number is less than 0, stick a negative sign in front.
Example using 32 bit numbers
We'll stay with -8 because it's been so good to us this whole time. So converting -8 to two's complement gives:
Convert: 0000 0000 0000 0000 0000 0000 0000 1000
Invert: 1111 1111 1111 1111 1111 1111 1111 0111
Add 1: 1111 1111 1111 1111 1111 1111 1111 1000
Separate: 11 111 111 111 111 111 111 111 111 111 000
Pad: 011 111 111 111 111 111 111 111 111 111 000
Convert: 3 7 7 7 7 7 7 7 7 7 0
Shorten: 37777777770
Which produces the result you're seeing when you call Oct(-8)
.
Armed with this knowledge, you can now also explain why Hex(-8)
produces 0xFFFFFFF8
. (And you can see why I used 8 bit numbers throughout most of this.)
1 For a overly detailed introduction to binary numbers, check out the Wikipedia article