Why does ^1 equal -2? - go

fmt.Println(^1)
Why does this print -2?

The ^ operator is the bitwise complement operator. Spec: Arithmetic operators:
For integer operands, the unary operators +, -, and ^ are defined as follows:
+x is 0 + x
-x negation is 0 - x
^x bitwise complement is m ^ x with m = "all bits set to 1" for unsigned x
and m = -1 for signed x
So 1 in binary is a single 1 bit preceded with full of zeros:
0000000000000000000000000000000000000000000000000000000000000001
So the bitwise complement is a single 0 bit preceded by full of ones:
1111111111111111111111111111111111111111111111111111111111111110
The ^1 is an untyped constant expression. When it is passed to a function, it has to be converted to a type. Since 1 is an untyped integer constant, its default type int will be used. int in Go is represented using the 2's complement where negative numbers start with a 1. The number being full ones is -1, the number being smaller by one (in binary) is -2 etc.
The bit pattern above is the 2's complement representation of -2.
To print the bit patterns and type, use this code:
fmt.Println(^1)
fmt.Printf("%T\n", ^1)
fmt.Printf("%064b\n", 1)
i := ^1
fmt.Printf("%064b\n", uint(i))
It outputs (try it on the Go Playground):
-2
int
0000000000000000000000000000000000000000000000000000000000000001
1111111111111111111111111111111111111111111111111111111111111110

Okay, this has to do with the way that we use signed signs in computation.
For a 1 byte number, you can get
D
B
-8
1000
-7
1001
-6
1010
-5
1011
-4
1100
-3
1101
-2
1110
-1
1111
0
0000
1
0001
2
0010
3
0011
4
0100
5
0101
6
0110
7
0111
You can see here that 1 is equivalent to 0001 (Nothing changes) but -1 is equal to 1111. ^ operator does a bitwise xor operation. Therefore:
0001
1111 xor
-------
1110 -> That is actually -2.
All this is because of the convention of two complement that we use to do calculations with negative numbers. Of course, this can be extrapolated to longer binary numbers.
You can test this by using windows calculator to do a xor bitwise calculation.

Related

different between "&" and "and" in expressions [duplicate]

This question already has answers here:
Boolean operators vs Bitwise operators
(9 answers)
Closed 4 months ago.
What the different between logical operators and, or and bitwise analogs &, | in usage? Is there any difference in efficiency in various solutions?
Logical operators operate on logical values, while bitwise operators operate on integer bits. Stop thinking about performance, and use them for they're meant for.
if x and y: # logical operation
...
z = z & 0xFF # bitwise operation
Bitwise = Bit by bit checking
# Example
Bitwise AND: 1011 & 0101 = 0001
Bitwise OR: 1011 | 0101 = 1111
Logical = Logical checking or in other words, you can say True/False checking
# Example
# both are non-zero so the result is True
Logical AND: 1011 && 0101 = 1 (True)
# one number is zero so the result is False
Logical AND: 1011 && 0000 = 0 (False)
# one number is non-zero so the result is non-zero which is True
Logical OR: 1011 || 0000 = 1 (True)
# both numbers are zero so the result is zero which is False
Logical OR: 0000 || 0000 = 0 (False)
Logical operators are used for booleans, since true equals 1 and false equals 0. If you use (binary) numbers other than 1 and 0, then any number that's not zero becomes a one. Ex: int x = 5; (101 in binary) int y = 0; (0 in binary) In this case, printing x && y would print 0, because 101 was changed to 1, and 0 was kept at zero: this is the same as printing true && false, which returns false (0). On the other hand, bitwise operators perform an operation on every single bit of the two operands (hence the term "bitwise"). Ex: int x = 5; int y = 8; printing x | y (bitwise OR) would calculate this: 000101 (5)| 1000 (8) ----------- = 1101 (13) Meaning it would print 13.

Hashing binary numbers with don't care bits

How can I find out if a binary number is contained in a set, where it is possible that an element of the set has don’t care bits?
I thought about using hash table, but there is a need to duplicate the numbers with don’t care bits in the hash table in order to cover all the possibilities.
For example:
The set of numbers is:
0 00x1
1 10xx
2 110x
3 1010
4 11x1
5 0010
and the number is 0011, the result should be 0.
If number of digits of binary number are limited then you can duplicate those don't care bits and convert the binary numbers to integers then use these integers as keys for map and other as values.
Example
0 00x1
1 10xx
can be converted to
0001 0
0011 0
1000 1
1001 1
1010 1
1011 1
and saved as
i j
1 0
3 0
8 1
9 1
10 1
11 1
where i is the key and j is the value
Let's say you have the binary number 1xxx, that would match 8 numbers. So, do not go with duplicating for each option.
You have to keep the "do not care" bits somewhere. Use another number for this, set the "do not care" bits to 1. If we go over your example:
i x y
0 00x1 0010
1 10xx 0011
2 110x 0001
3 1010 0000
4 11x1 0010
5 0010 0000
And you need to decide what to use for x, 0 or 1. You can use any of them, once you keep the information in the second number it does not matter.
Now use bitwise operations:
if ((n ^ x[i]) | y[i]) == y[i] then match
This solution is based on checking the existence of any non-matching bits except do-not-care bits. (n xor x[i]) gives the non-matching bits, then or'ing it with y[i] should not be different than y[i].
If we go over your example, and assuming you choose 0 for x, the check becomes
i:0 -->> ((0011 ^ 0001) | 0010) == 0010 -->> match!
i:1 -->> ((0011 ^ 1000) | 0011) != 0011 -->> no match!
i:2 -->> ((0011 ^ 1100) | 0001) != 0001 -->> no match!
i:3 -->> ((0011 ^ 1010) | 0000) != 0001 -->> no match!
i:4 -->> ((0011 ^ 1101) | 0010) != 0001 -->> no match!
i:5 -->> ((0011 ^ 0010) | 0000) != 0000 -->> no match!

How to bitmask a number (in hex) using the AND operator?

I know that you can bitmask by ANDing a value with 0. However, how can I both bitmask certain nibbles and maintain others. In other words if I have 0x000f0b7c and I wanted to mask the everything but b (in other words my result would be 0x00000b00) how would I use AND to do this? Would it require multiple steps?
You can better understand boolean operations if you represent values in binary form.
The AND operation between two binary digits returns 1 if both the binary digits have a value of 1, otherwise it returns 0.
Suppose you have two binary digits a and b, you can build the following "truth table":
a | b | a AND b
---+---+---------
0 | 0 | 0
1 | 0 | 0
0 | 1 | 0
1 | 1 | 1
The masking operation consists of ANDing a given value with a "mask" where every bit that needs to be preserved is set to 1, while every bit to discard is set to 0.
This is done by ANDing each bit of the given value with the corresponding bit of the mask.
The given value, 0xf0b7c, can be converted as follows:
f 0 b 7 c (hex)
1111 0000 1011 0111 1100 (bin)
If you want to preserve only the bits corresponding to the "b" value (bits 8..11) you can mask it this way:
f 0 b 7 c
1111 0000 1011 0111 1100
0000 0000 1111 0000 0000
The value 0000 0000 1111 0000 0000 can be converted to hex and has a value of 0xf00.
So if you calculate "0xf0b7c AND 0xf00" you obtain 0xb00.

Why this exponent got calculated in this way at this example?

Number: 0.1101112 × 2^–3 (the first bit is included in this example in the mantissa)
where 8 bits are used for the characteristic, and the exponent bias is
2^7 – 1
Their solution:
The sign bit is 0. The characteristic is –3 + 2^7 – 1, represented as an 8-
bit binary number. The simplest way to calculate the characteristic
here is to find the 7-bit 2’s complement of the binary representation
of 4 (= 3 + 1), and adjoin a leading zero:
Binary representation of 4: 0000100
2’s complement: 1111100
Characteristic: 0111 1100
Why: my solution was get the 8-bit instead of the 7-bit complement
1111 1100 then add it to 128 8-bit representation 1000 0000
Which get me 1 0111 1100 then ignoring the ninth column I got the same answer,
but i did not get the approach of the author.
Your explanation is highly appreciated
Thanks
The idea behind the original approach is to rewrite the expression
–3 + 2^7 – 1
as
2^7 - 4
The lower seven bits of this expression are the 7-bit two's complement of 4 (i.e. the representation of -4 in 7 bits). Since the number is obviously in the range 0-127, then eighth bit must be zero.

Query about working out whether number is a power of 2

Using the classic code snippet:
if (x & (x-1)) == 0
If the answer is 1, then it is false and not a power of 2. However, working on 5 (not a power of 2) and 4 results in:
0001 1111
0001 1111
0000 1111
That's 4 1s.
Working on 8 and 7:
1111 1111
0111 1111
0111 1111
The 0 is first, but we have 4.
In this link (http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/) for both cases, the answer starts with 0 and there is a variable number of 0s/1s. How does this answer whether the number is a power of 2?
You need refresh yourself on how binary works. 5 is not represented as 0001 1111 (5 bits on), it's represented as 0000 0101 (2^2 + 2^0), and 4 is likewise not 0000 1111 (4 bits on) but rather 0000 0100 (2^2). The numbers you wrote are actually in unary.
Wikipedia, as usual, has a pretty thorough overview.
Any power of two number can be represent in binary with a single 1 and multiple 0s.
eg.
10000(16)
1000(8)
100(4)
If you subtract 1 from any power of two number, you will get all 1s to the right of where the original one was.
10000(16) - 1 = 01111(15)
ANDing these two numbers will give you 0 every time.
In the case of a non-power of two number, subtracting one will leave at least one "1" unchanged somewhere in the number like:
10010(18) - 1 = 10001(17)
ANDing these two will result in
10000(16) != 0
Keep in mind that if x is a power of 2, there is exactly 1 bit set. Subtract 1, and you know two things: the resulting value is not a power of two, and the bit that was set is no longer set. So, when you do a bitwise and &, every bit that was set in x is not unset, and all the bits in (x-1) that are set must be matched against bits not set in x. So the and of each bit is always 0.
In other words, for any bit pattern, you are guaranteed that (x&(x-1)) is zero.
((n & (n-1)) == 0)
It checks whether the value of “n” is a power of 2.
Example:
if n = 8, the bit representation is 1000
n & (n-1) = (1000) & ( 0111) = (0000)
So it return zero only if its value is in power of 2.
The only exception to this is ‘0’.
0 & (0-1) = 0 but ‘0’ is not the power of two.
Why does this make sense?
Imagine what happens when you subtract 1 from a string of bits. You read from left to right,
turning each 0 to a 1 until you hit a 1, at which point that bit is flipped:
1000100100 -> (subtract 1) -> 1000100011
Thus, every bit, up through the first 1, is flipped. If there’s exactly one 1 in the number, then every bit (other than the leading zeros) will be flipped. Thus, n & (n-1) == 0 if there’s exactly one 1. If there’s exactly one 1, then it must be a power of two.

Resources