bitwise operator XOR [duplicate] - c

This question already has answers here:
How does XOR work in C to find a number occurring odd number of times?
(4 answers)
Closed 6 years ago.
Trying to understand the XOR importance, I found this code:
Given a set of numbers where all elements occur even number of times except one number, find the odd occurring number
But I can't visualize it.
How does the XOR bitwise operator roll out the odd element?
// Function to return the only odd occurring element
int findOdd(int arr[], int n) {
int res = 0, i;
for (i = 0; i < n; i++)
res ^= arr[i];
return res;
}
int main(void) {
int arr[] = { 12, 12, 14, 90, 14, 14, 14 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("The odd occurring element is %d\n", findOdd(arr, n));
return 0;
}
Output: The odd occurring element is 90

The way I read it you are really asking two questions:
What is the importance of XOR?
How does XOR help find the odd occurrence of a number in a series?
In order to understand question (2), one must understand question (1). Understanding question (1) requires an adequate introduction to the XOR logic and the properties it has.
What is the importance of XOR?
Definition: The output of an XOR operation is TRUE if and only if the number of TRUE inputs are odd. Commonly referred to as "one or the other, but not both"
This is captured by the following truth table:
XOR Truth Table
Using the truth table it is trivial to derive the following properties:
A ^ 0 = A (The output follows the variable input)
A ^ 1 = A' (The output is the negation of the variable input)
A ^ A = 0 (The output is always zero since both inputs are equal)
(A ^ B) ^ C = A ^ (B ^ C) (Associative Property)
A ^ B = B ^ A (Communative Property)
Now on to the importance of XOR, i.e., how these properties allow folks to make useful things. The first computing layer to note is the hardware layer. XOR gates are physical devices that have utility in many fundamental logic circuits, that fundamental utility being "odd occurrence detection". Some notable applications:
Half-Adders: The truth table for a half-adders SUM output is identical to the XOR gate. (Throw an AND gate in for the carry bit). Same thing for the Full-Adder, using XOR gates for the fundamental summation with some additional supporting gates.
Inverters: Using one input as a control and the other as the "input", the xor gate can be used to invert the input signal. The control bit can be used to pass the input through as well, acting as a buffer. In software, you use these circuits to toggle bits/bytes from one state to the other. Val = Val ^ 1 (Recall the second property above).
Comparators: The output of an XOR gate is 1 when the inputs are different, 0 when they are the same. This is the driving logic for the half-adder.
In addition to these circuits we can, at a hardware level, use XOR to check byte parity for Error Detection and Correction (EDAC) operations, swap register values (without a temp variable!), and recover corrupted/lost data from hard drives in a RAID system.
However, software junkies don't care about these circuits, they want to live in the land of abstractions that provide an easy way to use this hardware in a human intuitive way. Let there be code.
How does XOR help find the odd occurrence of a number in a series?
Even though the first comment to your question indicates the poster didn't understand your question, they inadvertently answered the question correctly, but I will explain further.
Let's break down what your findOdd() function is actually doing. The for loop is literally performing the following calculation:
Result = 0 ^ 12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14
Recall that XOR is communative, so after a little re-ordering the calculation becomes:
Result = 0 ^ 12 ^ 12 ^ 14 ^ 14 ^ 14 ^ 14 ^ 90
Using the property A ^ A = 0 and associativity, the XOR of 12 and 12 drops to 0 as does the XOR of the 14's, leaving:
Result = 0 ^ 0 ^ 0 ^ 0 ^ 90 = 0 ^ 90 = 90
In effect, the XOR forces even occurrences to become zero and A ^ 0 = A. Hope this verbose description of XOR was helpful in visualizing what is happening under the hood.

Binary XOR is the exclusive or operation, performed one bit at a time. It is equivalent to subtraction, modulo 2.
Here is the truth table for XOR:
a b a^b
1 0 1
1 1 0
0 0 0
0 1 1
As you can see, XOR sets a bit to 1 (true) when EITHER of the input bits is 1, but not both.
Now, consider this: what is 1 xor 1? From the truth table, you know it's zero.
And what is 1 xor 1 xor 1? Well, you know 1^1==0, so that leaves 0^1, which is 1.
So you have that xor'ing a 1 bit an even number of times will produce a zero, and an odd number of times will produce a 1.
Thus, if we take a ^ a ^ a, for some value of a, we get a result where all the 1 bits in the binary representation of a are set. (Which is to say, we get back 'a'.)
Whereas if we take a ^ a ^ a ^ a, for some value of a, we get a result where all the 1 bits in the binary representation of a are 0. (Which is to say, we get back 0.)
The one exception to this, of course, is 0. The binary representation for 0 has no set bits in it, so this approach will not indicate if the number of 0's was even or odd.

But I can't visualize it
Then you should step through the code one line at a time and keep an eye on res at each iteration through the loop.
Or just do it on paper -- write down the binary form of 12, i.e. 00001100, and then XOR that value with the next value, also 00001100, which gets you back to 00000000. Then XOR the next value with that, and so on. You might want to start with a short list of pairs of numbers, like {12, 12, 15, 15} and see what happens. Then try removing the last one, so you have {12, 12, 15} and see what you get. Then try reordering the list: {12, 15, 12}. Count the number of times that each bit gets flipped.

XOR means exclusive or, for each bit in the operands, the resulting bit is 1 if either corresponding bit of the operand is 1 but not both:
0 ^ 0 = 0, 1 ^ 0 = 1, 1 ^ 0 = 0 and 1 ^ 1 = 0.
Identical numbers cancel each other as x ^ x == 0 for all values. The final outcome of xoring all elements of the array is the number occurring an odd number of times, assuming there is only one.
This method works if all duplicate numbers but one occur an even number of times and if there is a single entry occurring an odd number of times.

XOR is commutative: a ^ b equals b ^ a.
XOR is associative: a ^ (b ^ c) equals (a ^ b) ^ c.
Together these two mean that you can arbitrarily reorder operands in a chain of XORs.
Furthermore:
0 is a neutral element: a ^ 0 equals a.
Every number is its own inverse: a ^ a equals 0.
In your code we're doing 12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14.
We can reorder this to (12 ^ 12) ^ (14 ^ 14) ^ (14 ^ 14) ^ 90, pairing up every element that occurs an even number of times with itself.
This simplifies to 0 ^ 0 ^ 0 ^ 90 (because all pairs of equal elements cancel each other out, giving 0), which reduces to just 90 (because XORing with 0 does nothing).

This is all about XOR operator.
^ is bit-wise XOR.
For example,
12^5 == 1100^0101 == (1^0)(1^1)(0^1)(0^1) == 1011
From the mathematical definition of XOR, the output is 1 iif the number of 1(s) in inputs is odd.
This case:
When a number occurs even number of times, the binary representation will also get two 1s or two 0s in each position, making the result going to 0.
Eg:
2^2^3 == (1^1^1)(0^0^1) == 11 == 3
i.e. 10 (2)
10 (2)
11 (3)
--------
11 (3)
========
5^7^5 == (1^1^1)(0^1^0)(1^1^1) == 111
101 (5)
111 (7)
101 (5)
---------
111 (7)
=========
Note that even occurring numbers have no affect here.

Given the following axioms:
x ^ x == 0
y ^ y ^ y == y
z ^ 0 == z
Then for example:
x ^ x ^ y ^ y ^ y == y
\___/ \_______/
0 ^ y == y
Also:
x ^ y == y ^ x
So the order of the operands does not matter.
The point is an odd number of occurrences of a value results in the value, while even results in zero, and a value xor'ed with zero is the value.
Consequently as the comment at the start of the code suggests, it works only when there is a single value with an odd number of occurrences and all other values occur an even number of times. Otherwise the result is simply the xor of all the odd occurring values, e.g.:
x ^ x ^ x ^ y == x ^ y
which is neither x nor y.

Related

Recurrence relation for the algorithm

I have already given the following algorithm which I have to find the recurrence relation.
int Recursive(int n)
{
if(n<=1)
return n;
sum=0;
for(int j=0;j<n;j++)
sum++;
return Recursive(n/2) + Recursive(n/2) + sum;
}
I have obtained recurrence relation for the above algorithm as
T(n) = 2 T(n/2) + constant
But I am not sure about the constant part of this recurrence relation since we have sum in the algorithm. Just to clarify, sum is a global variable - the lack of declaration is not a typo.
Can anyone help me out to get the correct recurrence relation? Thanks.
Assumptions made in this answer:
sum is declared globally – since the apparently missing declaration is, as you stated, not a typo.
The question asks for the return value, not the time complexity.
The expressions in the return statement are evaluated in their order of appearance; this is not guaranteed by the C standard, so the answer is technically undefined.
Note that, since each call does either:
Returns its argument (if n <= 1)
Resets the value of sum to 0
... the function is guaranteed to be "closed", in the sense that its return value will only depend on its argument. It follows that:
The two separate calls to Recursive(n / 2) can be combined into just one call, without impacting the return value: return 2 * Recursive(n / 2) + sum;.
From this point on-wards is it assumed that this modification has been applied to the original code; this helps in clarifying the flow of the program, since there will now only be one path of execution (instead of branches created by two calls).
Now for the key part. The call to Recursive(n / 2) overwrites the value of sum before the function returns, undoing the work done by the preceding for-loop. This overwriting behavior continues down the recursion hierarchy, until the final call when the stopping condition n <= 1 is hit (it just returns n instead). It follows that:
There is only one value of sum which contributes to the final return value, given by its value after the penultimate call to Recursive.
Due to truncation by integer division, when the penultimate call is performed n is always 2 or 3 (both of which satisfy n / 2 = 1); these are thus also the possible final values of sum.
What values of n give sum = 2 and sum = 3 respectively? It is illustrative to consider the binary representation of n.
Integer division by 2 is equivalent to shifting the bit-pattern "right" by 1 (or "left" depending on endian-ness...), and discarding the least-significant bit. It follows that the final value of sum depends on only the 2 most significant bits of n:
initial bit-pattern >> penultimate call
-----------------------------------------
...000 10 xxx... ...0000 10 = 2
...000 11 xxx... ...0000 11 = 3
xxx: discarded bits
The bit-pattern of n has floor(log2(n)) + 1 significant bits; the final value of sum can therefore be compactly expressed as:
S(n) = 2 + second_most_significant_bit(n)
How many times is sum added to the return value? The number of recursive calls to Recursive (i.e. the total number of calls minus one, including the initial call, but excluding the final). This is given by floor(log2(n)):
Note that the return value of the final call will always be 1 if initially n >= 1. Therefore the final return value of Recursive is given by:
Test C code for confirmation:
// override the library definition of log2 to use integers only
int log2(int n) {
int b = 0;
while ((n >>= 1) != 0)
b++;
return b;
}
// get i-th bit from bit pattern of n
int get_bit(int n, int i) {
return (n >> (i - 1)) & 1;
}
// calculating return value of Recursive using equation above
int Value(int n) {
int l2n = log2(n); // floor(log2(n))
int p2l = 1 << l2n; // 2^(floor(log2(n)))
return p2l + (p2l - 1) * (2 + get_bit(n, l2n));
}
Results:
n | Recursive Value
-------------------------------
2 | 4 4
3 | 5 5
4 - 5 | 10 10
6 - 7 | 13 13
8 - 11 | 22 22
12 - 15 | 29 29
16 - 23 | 46 46
24 - 31 | 61 61
32 - 47 | 94 94
48 - 63 | 125 125
64 - 95 | 190 190
I am not sure about the constant part of this recurrence relation
There is no constant part, since sum equals n after the loop. This gives:
T(n) = 2T(n/2)+n
So if the sum is global variable, T(n) = 2T(n/2)+C(Constant) and if sum is local variable T(n) = 2T(n/2)+n . Am I correct?
No, as mch wrote:
It seems that sum is a global variable… In this case it would be unspecified if sum or one of the Recursive(n/2) will be evaluated first.
This means it would be unspecified whether T(n) = 2T(n/2)+n or T(n) = 2T(n/2)+n/2; in neither case there's a constant part.

Is this how the + operator is implemented in C?

When understanding how primitive operators such as +, -, * and / are implemented in C, I found the following snippet from an interesting answer.
// replaces the + operator
int add(int x, int y) {
while(x) {
int t = (x & y) <<1;
y ^= x;
x = t;
}
return y;
}
It seems that this function demonstrates how + actually works in the background. However, it's too confusing for me to understand it. I believed that such operations are done using assembly directives generated by the compiler for a long time!
Is the + operator implemented as the code posted on MOST implementations? Does this take advantage of two's complement or other implementation-dependent features?
To be pedantic, the C specification does not specify how addition is implemented.
But to be realistic, the + operator on integer types smaller than or equal to the word size of your CPU get translated directly into an addition instruction for the CPU, and larger integer types get translated into multiple addition instructions with some extra bits to handle overflow.
The CPU internally uses logic circuits to implement the addition, and does not use loops, bitshifts, or anything that has a close resemblance to how C works.
When you add two bits, following is the result: (truth table)
a | b | sum (a^b) | carry bit (a&b) (goes to next)
--+---+-----------+--------------------------------
0 | 0 | 0 | 0
0 | 1 | 1 | 0
1 | 0 | 1 | 0
1 | 1 | 0 | 1
So if you do bitwise xor, you can get the sum without carry.
And if you do bitwise and you can get the carry bits.
Extending this observation for multibit numbers a and b
a+b = sum_without_carry(a, b) + carry_bits(a, b) shifted by 1 bit left
= a^b + ((a&b) << 1)
Once b is 0:
a+0 = a
So algorithm boils down to:
Add(a, b)
if b == 0
return a;
else
carry_bits = a & b;
sum_bits = a ^ b;
return Add(sum_bits, carry_bits << 1);
If you get rid of recursion and convert it to a loop
Add(a, b)
while(b != 0) {
carry_bits = a & b;
sum_bits = a ^ b;
a = sum_bits;
b = carrry_bits << 1; // In next loop, add carry bits to a
}
return a;
With above algorithm in mind explanation from code should be simpler:
int t = (x & y) << 1;
Carry bits. Carry bit is 1 if 1 bit to the right in both operands is 1.
y ^= x; // x is used now
Addition without carry (Carry bits ignored)
x = t;
Reuse x to set it to carry
while(x)
Repeat while there are more carry bits
A recursive implementation (easier to understand) would be:
int add(int x, int y) {
return (y == 0) ? x : add(x ^ y, (x&y) << 1);
}
Seems that this function demonstrates how + actually works in the
background
No. Usually (almost always) integer addition translates to machine instruction add. This just demonstrate an alternate implementation using bitwise xor and and.
Seems that this function demonstrates how + actually works in the background
No. This is translated to the native add machine instruction, which is actually using the hardware adder, in the ALU.
If you're wondering how does the computer add, here is a basic adder.
Everything in the computer is done using logic gates, which are mostly made of transistors. The full adder has half-adders in it.
For a basic tutorial on logic gates, and adders, see this. The video is extremely helpful, though long.
In that video, a basic half-adder is shown. If you want a brief description, this is it:
The half adder add's two bits given. The possible combinations are:
Add 0 and 0 = 0
Add 1 and 0 = 1
Add 1 and 1 = 10 (binary)
So now how does the half adder work? Well, it is made up of three logic gates, the and, xor and the nand. The nand gives a positive current if both the inputs are negative, so that means this solves the case of 0 and 0. The xor gives a positive output one of the input is positive, and the other negative, so that means that it solves the problem of 1 and 0. The and gives a positive output only if both the inputs are positive, so that solves the problem of 1 and 1. So basically, we have now got our half-adder. But we still can only add bits.
Now we make our full-adder. A full adder consists of calling the half-adder again and again. Now this has a carry. When we add 1 and 1, we get a carry 1. So what the full-adder does is, it takes the carry from the half-adder, stores it, and passes it as another argument to the half-adder.
If you're confused how can you pass the carry, you basically first add the bits using the half-adder, and then add the sum and the carry. So now you've added the carry, with the two bits. So you do this again and again, till the bits you have to add are over, and then you get your result.
Surprised? This is how it actually happens. It looks like a long process, but the computer does it in fractions of a nanosecond, or to be more specific, in half a clock cycle. Sometimes it is performed even in a single clock cycle. Basically, the computer has the ALU (a major part of the CPU), memory, buses, etc..
If you want to learn computer hardware, from logic gates, memory and the ALU, and simulate a computer, you can see this course, from which I learnt all this: Build a Modern Computer from First Principles
It's free if you do not want an e-certificate. The part two of the course is coming up in spring this year
C uses an abstract machine to describe what C code does. So how it works is not specified. There are C "compilers" that actually compile C into a scripting language, for example.
But, in most C implementations, + between two integers smaller than the machine integer size will be translated into an assembly instruction (after many steps). The assembly instruction will be translated into machine code and embedded within your executable. Assembly is a language "one step removed" from machine code, intended to be easier to read than a bunch of packed binary.
That machine code (after many steps) is then interpreted by the target hardware platform, where it is interpreted by the instruction decoder on the CPU. This instruction decoder takes the instruction, and translates it into signals to send along "control lines". These signals route data from registers and memory through the CPU, where the values are added together often in an arithmetic logic unit.
The arithmetic logic unit might have separate adders and multipliers, or might mix them together.
The arithmetic logic unit has a bunch of transistors that perform the addition operation, then produce the output. Said output is routed via the signals generated from the instruction decoder, and stored in memory or registers.
The layout of said transistors in both the arithmetic logic unit and instruction decoder (as well as parts I have glossed over) is etched into the chip at the plant. The etching pattern is often produced by compiling a hardware description language, which takes an abstraction of what is connected to what and how they operate and generates transistors and interconnect lines.
The hardware description language can contain shifts and loops that don't describe things happening in time (like one after another) but rather in space -- it describes the connections between different parts of hardware. Said code may look very vaguely like the code you posted above.
The above glosses over many parts and layers and contains inaccuracies. This is both from my own incompetence (I have written both hardware and compilers, but am an expert in neither) and because full details would take a career or two, and not a SO post.
Here is a SO post about an 8-bit adder. Here is a non-SO post, where you'll note some of the adders just use operator+ in the HDL! (The HDL itself understands + and generates the lower level adder code for you).
Almost any modern processor that can run compiled C code will have builtin support for integer addition. The code you posted is a clever way to perform integer addition without executing an integer add opcode, but it is not how integer addition is normally performed. In fact, the function linkage probably uses some form of integer addition to adjust the stack pointer.
The code you posted relies on the observation that when adding x and y, you can decompose it into the bits they have in common and the bits that are unique to one of x or y.
The expression x & y (bitwise AND) gives the bits common to x and y. The expression x ^ y (bitwise exclusive OR) gives the bits that are unique to one of x or y.
The sum x + y can be rewritten as the sum of two times the bits they have in common (since both x and y contribute those bits) plus the bits that are unique to x or y.
(x & y) << 1 is twice the bits they have in common (the left shift by 1 effectively multiplies by two).
x ^ y is the bits that are unique to one of x or y.
So if we replace x by the first value and y by the second, the sum should be unchanged. You can think of the first value as the carries of the bitwise additions, and the second as the low-order bit of the bitwise additions.
This process continues until x is zero, at which point y holds the sum.
The code that you found tries to explain how very primitive computer hardware might implement an "add" instruction. I say "might" because I can guarantee that this method isn't used by any CPU, and I'll explain why.
In normal life, you use decimal numbers and you have learned how to add them: To add two numbers, you add the lowest two digits. If the result is less than 10, you write down the result and proceed to the next digit position. If the result is 10 or more, you write down the result minus 10, proceed to the next digit, buy you remember to add 1 more. For example: 23 + 37, you add 3+7 = 10, you write down 0 and remember to add 1 more for the next position. At the 10s position, you add (2+3) + 1 = 6 and write that down. Result is 60.
You can do the exact same thing with binary numbers. The difference is that the only digits are 0 and 1, so the only possible sums are 0, 1, 2. For a 32 bit number, you would handle one digit position after the other. And that is how really primitive computer hardware would do it.
This code works differently. You know the sum of two binary digits is 2 if both digits are 1. So if both digits are 1 then you would add 1 more at the next binary position and write down 0. That's what the calculation of t does: It finds all places where both binary digits are 1 (that's the &) and moves them to the next digit position (<< 1). Then it does the addition: 0+0 = 0, 0+1 = 1, 1+0 = 1, 1+1 is 2, but we write down 0. That's what the excludive or operator does.
But all the 1's that you had to handle in the next digit position haven't been handled. They still need to be added. That's why the code does a loop: In the next iteration, all the extra 1's are added.
Why does no processor do it that way? Because it's a loop, and processors don't like loops, and it is slow. It's slow, because in the worst case, 32 iterations are needed: If you add 1 to the number 0xffffffff (32 1-bits), then the first iteration clears bit 0 of y and sets x to 2. The second iteration clears bit 1 of y and sets x to 4. And so on. It takes 32 iterations to get the result. However, each iteration has to process all bits of x and y, which takes a lot of hardware.
A primitive processor would do things just as quick in the way you do decimal arithmetic, from the lowest position to the highest. It also takes 32 steps, but each step processes only two bits plus one value from the previous bit position, so it is much easier to implement. And even in a primitive computer, one can afford to do this without having to implement loops.
A modern, fast and complex CPU will use a "conditional sum adder". Especially if the number of bits is high, for example a 64 bit adder, it saves a lot of time.
A 64 bit adder consists of two parts: First, a 32 bit adder for the lowest 32 bit. That 32 bit adder produces a sum, and a "carry" (an indicator that a 1 must be added to the next bit position). Second, two 32 bit adders for the higher 32 bits: One adds x + y, the other adds x + y + 1. All three adders work in parallel. Then when the first adder has produced its carry, the CPU just picks which one of the two results x + y or x + y + 1 is the correct one, and you have the complete result. So a 64 bit adder only takes a tiny bit longer than a 32 bit adder, not twice as long.
The 32 bit adder parts are again implemented as conditional sum adders, using multiple 16 bit adders, and the 16 bit adders are conditional sum adders, and so on.
My question is: Is the + operator implemented as the code posted on MOST implementations?
Let's answer the actual question. All operators are implemented by the compiler as some internal data structure that eventually gets translated into code after some transformations. You can't say what code will be generated by a single addition because almost no real world compiler generates code for individual statements.
The compiler is free to generate any code as long as it behaves as if the actual operations were performed according to the standard. But what actually happens can be something completely different.
A simple example:
static int
foo(int a, int b)
{
return a + b;
}
[...]
int a = foo(1, 17);
int b = foo(x, x);
some_other_function(a, b);
There's no need to generate any addition instructions here. It's perfectly legal for the compiler to translate this into:
some_other_function(18, x * 2);
Or maybe the compiler notices that you call the function foo a few times in a row and that it is a simple arithmetic and it will generate vector instructions for it. Or that the result of the addition is used for array indexing later and the lea instruction will be used.
You simply can't talk about how an operator is implemented because it is almost never used alone.
In case a breakdown of the code helps anyone else, take the example x=2, y=6:
x isn't zero, so commence adding to y:
while(2) {
x & y = 2 because
x: 0 0 1 0 //2
y: 0 1 1 0 //6
x&y: 0 0 1 0 //2
2 <<1 = 4 because << 1 shifts all bits to the left:
x&y: 0 0 1 0 //2
(x&y) <<1: 0 1 0 0 //4
In summary, stash that result, 4, in t with
int t = (x & y) <<1;
Now apply the bitwise XOR y^=x:
x: 0 0 1 0 //2
y: 0 1 1 0 //6
y^=x: 0 1 0 0 //4
So x=2, y=4. Finally, sum t+y by resetting x=t and going back to the beginning of the while loop:
x = t;
When t=0 (or, at the beginning of the loop, x=0), finish with
return y;
Just out of interest, on the Atmega328P processor, with the avr-g++ compiler, the following code implements adding one by subtracting -1 :
volatile char x;
int main ()
{
x = x + 1;
}
Generated code:
00000090 <main>:
volatile char x;
int main ()
{
x = x + 1;
90: 80 91 00 01 lds r24, 0x0100
94: 8f 5f subi r24, 0xFF ; 255
96: 80 93 00 01 sts 0x0100, r24
}
9a: 80 e0 ldi r24, 0x00 ; 0
9c: 90 e0 ldi r25, 0x00 ; 0
9e: 08 95 ret
Notice in particular that the add is done by the subi instruction (subtract constant from register) where 0xFF is effectively -1 in this case.
Also of interest is that this particular processor does not have a addi instruction, which implies that the designers thought that doing a subtract of the complement would be adequately handled by the compiler-writers.
Does this take advantage of two's complement or other implementation-dependent features?
It would probably be fair to say that compiler-writers would attempt to implement the wanted effect (adding one number to another) in the most efficient way possible for that particularly architecture. If that requires subtracting the complement, so be it.

Fixed point code division understanding

Code for division by 9 in fixed point.
1. q = 0; // quotient
2. y = (x << 3) - x; // y = x * 7
3. while(y) { // until nothing significant
4. q += y; // add (effectively) binary 0.000111
5. y >>= 6; // realign
6. }
7. q >>= 6; // align
Line 2 through 5 in the FIRST execution of while loop is effectively doing
x*.000111 (in decimal representation x*0.1), what it is trying to achieve in subsequent while loops?
Should it not be again multiplying that with 7 and again shifting instead
of doing only shifting to take care of recurrence?
Explanation with respect to plain decimal number multiplication as to what is being achieved with only shifting would be nice.
Detailed code explanation here:
Divide by 9 without using division or multiplication operator
Lets denote 7/64 by the letter F. 7/64 is represented in binary as 0.000111 and is very close to 1/9. But very close is not enough. We want to use F to get exactly to 1/9.
It is done in the following way
F+ (F/64) + (F/64^2) + (F/64^3) + (F/64^4)+ (F/64^5) + ...
As we add more elements to this sequence the results gets closer to 1/9
Note each element in the sequence is exactly 1/64 from previous element.
A fast way to divide by 64 is >>6
So effectively you want to build a loop which sums this sequence. You start from F and in each iteration do F>>6 and add it to the sum.
Eventually (after enough iterations) the sum will be exactly 1/9.
Ok now, you are ready to understand the code.
Instead of using F (which is a fraction and cannot be represented in fixed points) the code multiplies F by x.
So the sum of the sequence will be X/9 instead of 1/9
Moreover in order to work with fixed points it is better to store 64*X*F and the result would by 64*X/9.
Later after the summation we can divide by 64 to get the X/9
The code stores in the variable y the value of F*x*64
variable q stores the sum of the sequence. In each loop iteration we generate the next element in the sequence by dividing the previous element by 64 (y>>=6)
Finally after the loop we divide the sum by 64 (q>>=6) and get the result X/9.
Regarding you question. We should not multiply by 7 each time or else we will get a sum of the sequence of
F+ (F^2) + (F^3) + (F^4) + (F^5)...
This would yield a result of ~X/(8+1/7) instead of X/9.
Shifting by one to the left multiplies by two, shifting by one to the right divides by two. Why?
Shifting is the action of taking all the bits from your number and moving them n bits to the left/right. For example:
00101010 is 42 in Binary
42 << 2 means "shift 42 2 bits to the left" the result is
10101000 which is 168 in Binary
we multiplied 42 by 4.
42 >> 2 means "shift 42 2 bits to the right" the result is
00001010 which is 10 in binary (Notice the rightmost bits have been discarded)
we divided 42 by 4.
Similarly : (x << 3) is x * 8, so (x << 3) - x is (x * 8) - x => x * 7

XOR operation returning only non-pair element in integer array

I came across this problem while solving challenges on Hackerrank.
/*
Problem Statement
There are N integers in an array A. All but one integer occur in pairs. Your task is to find the number that occurs only once.
Input Format
The first line of the input contains an integer N, indicating the number of integers. The next line contains N space-separated integers that form the array A.
Constraints
1≤N<100
N % 2=1 (N is an odd number)
0≤A[i]≤100,∀i∈[1,N]
Output Format
Output S, the number that occurs only once.
*/
The normal solution which I would write in this case turned out to be extremely complicated, with lots of nested if loops. On searching a bit, I found this solution which solves the problem by simply XOR-ing all the elements in the integer array with each other, and the result is the lonely integer.
Here's the related method (main() method which accepts input and parses it into integer array not shown as it's not relevant here) :
static int lonelyinteger(int[] a) {
int n = a.length;
int result = 0;
for( int i = 0; i < n; i++) {
result = result ^ a[i];
}
return result;
}
I am not sure how this XOR operation is able to return the "lonely integer" in the array. I'm aware of the two properties of XOR, as:
1. a^a=0
2. a^0=a
But other than this, I couldn't quite figure out how XOR worked here.
There is another question on SO with the same content, but that asks a different question, so I had to ask this (again).
I'd highly appreciate if anyone could provide a detailed explanation for this XOR operation.
Since a^a is equal to 0 for any a, all of the matching pairs of integers will cancel each other out, leaving 0. That is then XOR'ed with the final number. Since 0^a is equal to a for any a, the result will be that final number.
Simple demo:
$ ruby -e 'puts [1,1,2,2,3,3,4,5,5,6,6].reduce :^'
4
You can see why this works if you go through the individual pairs:
1 ^ 1 = 0
0 ^ 2 = 2
2 ^ 2 = 0
0 ^ 3 = 3
3 ^ 3 = 0
0 ^ 4 = 4
4 ^ 5 = 1
1 ^ 5 = 4
4 ^ 6 = 2
2 ^ 6 = 4
The result toggles between 0 and the latest number until you get to the loner; after that it toggles between that number and... whatever you get when you XOR it with the latest new number. The actual value there doesn't matter because it will be zapped when you XOR in the second copy of that number, and you're back to the copy of the singleton.
I sorted the numbers to make it easy to spot the singleton, but since XOR undoes itself, the order doesn't matter at all:
$ ruby -e 'puts [6,3,4,1,1,2,2,6,3,5,5].reduce :^'
4
6 ^ 3 is ... some number, and then that number ^ 4 is some other number, and then you XOR that with 1, and none of that matters because then you undo the 1, and then you throw in another intermediate result with the 2 and undo it right away, and then you undo the 6 and the 3, so you're back to just the 4. Which you XOR with 5 to get another ephemeral number that is then washed away by the final 5, leaving, once again, 4.

Bitwise C programming

Hey I have been having trouble with a C program. The program I have to write simulates the operation of a VAX computer. I have to take in 2 variables x and y to generate z.
within that there are two functions, the first
Sets Z to 1 where each bit position of y = 1
2nd sets z to 0 where each bit position of y = 1
I'm not asking for someone to do this for me, I just need an explanation on how this is carried out as I have a bare bones of the two functions that I need. I was thinking of something like this but I don't know if it's right at all.
#include<stdio.h>
int main()
{
int x1 = 1010;
int y1 = 0101;
bis(x1, y1);
bic(x1, y1);
}
/* BIT SET function that sets the result to 1 wherever y = 1 */
int bis (int x, int y)
{
int z = x & y;
int result = ?;
printf("BIT SET: \n\n", result);
return result;
}
/* BIT CLEAR function that sets result to 0 wherever y = 1 */
int bic(int x, int y)
{
int z = x & y;
int result = ?;
printf("BIT CLEAR:\n\n ", result);
return result;
}
Apologies for the poor naming conventions. Am I anyway on the right track for this program?
Let's look at bitset() first. I won't post C code, but we can solve this on paper as a start.
Say you have your integers with the following bit patterns: x = 1011 and y = 0101. (I'm changing your example numbers. And, incidentally, this is not how you would define two integers having these bit patterns, but right now we're focusing on the logic.)
If I am understanding correctly, when you call bitset(x, y), you want the answer, Z, to be 1111.
x = 1011
y = 0101
^ ^-------- Because these two bits have the value 1, then your answer also
has to set them to 1 while leaving the other bits in x alone.
Well, which bitwise operation will accomplish this? You have AND (&), OR (\), XOR (^), and COMPLEMENT (~).
In this case, you are ORing the two values. Looking at the following truth table:
x 1 0 1 1
y 0 1 0 1
-----------------
(x OR y) 1 1 1 1
Each bit in the last row is given by ORing that column in x and y. So (1 OR 0) = 1, (0 OR 1) = 1, (1 OR 0) = 1, (1 OR 1) = 1
So now you can write a C function bitset(x, y), ORs x and y, and returns the result as Z.
What bitwise operator - and you can do it in multiple steps with multiple operators - would you use to clear the bits?
x 1 0 1 1
y 0 1 0 1
-------------------------------------------
(SOME OPERATONS INVOLVING x and y) 1 0 1 0
What would those logical operators (from the list above) be? Think about the "and" and "complement" operators.
Good luck on your hw!
Bonus: A quick primer on expressing integers in C.
int x = 1337 creates an integer and gives it the value 1337. If you said x = 01337, x WILL NOT have the value "1337" like you might expect. By placing the 0 in front of the number, you're telling C that that number is in octal (base 8). The digits "1337", interpreted in base 8, is equivalent to decimal (base 10) 735. If you said x = 0x1337 then you are expressing the number in base 16, as a hexadecimal, equivalent to 4919 in base 10.
Nope... what you have there will and together two integers. One of which is 1010 (base10), and the other of which is 101 (base 8 - octal -> 65 base 10).
First you'll want to declare your constants as binary (by prefixing them with 0b).
Second, you'll want to out put them (for your instructor or TA) as a binary representation. Check out this question for more ideas

Resources