Can XOR of two integers go out of bounds?

C++CBit ManipulationInteger OverflowBitwise Xor

C++ Problem Overview


I had been studying the algorithm for finding lonely integers in an array, and here is the implementation:

int arr[] = {10, 20, 30, 5, 20, 10, 30};
int LonelyInteger = 0;
for(int i=0; i< 7; i++)
{
    LonelyInteger = LonelyInteger ^ arr[i];
}

The result is 5.

My question is - supposedly the integers (getting generated by the XOR operation) are too large due to this operation:

LonelyInteger ^ arr[i]

Which leads to a potentially large integer which cannot be represented by the datatype say int in this case. My questions are:

  1. Is it even possible that XOR will generate such a large integer value that cannot be stored in the int type?
  2. If it is not possible that this can happen then is there a proof for this?

C++ Solutions


Solution 1 - C++

XOR will never go out of bounds because it combines bits and doesn't create new bits where no bits were set before.

The result 5 is correct. Look at the binary representation of your value and the XOR result

10    00001010
20    00010100
30    00011110
 5    00000101
20    00010100
10    00001010
30    00011110
--------------
      00000101 => 5

An easy help for calculating a result of many XORed values is: The result will have a bit set where an odd number of bits are combined, no bit set for even number of bits.

> If it is not possible that this can happen then is there a proof for this?

XOR is equivalent to addition without carry on the individual bits. When you add bits without carry, no overflow can happen and so the int value can't go out of bounds.

Solution 2 - C++

The result can never be "too large" in the sense of its representation requiring more bits than int provides, since the operation is defined to combine bit values of its operands, not produce any new bits. Perhaps a better question might be, can the result be something other than a valid value representation of an int?

For unsigned integers, no. All bit patterns, and hence the result of all bitwise operations, are valid value representations.

For signed integers, it depends on the implementation-defined representation of negative values. Every implementation you're likely to encounter uses 2's-complement, in which again every bit pattern is valid; so again, the result of any bitwise operation will be a valid representation.

However, the standard also allows other representations, in which there may be one or more invalid bit patterns. In that case, it's possible for a bitwise operation, with two valid operands, to produce that pattern, and hence produce an invalid result.

Solution 3 - C++

(This post applies to C, not C++)

The bitwise operators cannot cause a trap representation due to setting invalid padding bits, see C11 6.2.6.2/1 footnote:

>...no arithmetic operation on valid values can generate a trap representation...

(The meaning of "arithmetic operation" is unclear but the index links to 6.5.11 which is the definition of XOR).

However, in C they can cause a negative zero to be generated. In 2's complement there is no negative zero. But say you were on a system with 1's complement then you could generate negative zero via ^ and this might cause a trap representation. 6.2.6.2/3 explicitly says that this is possible:

>If the implementation supports negative zeros, they shall be generated only by: > > — the &, |, ^, ~, <<, and >> operators with operands that produce such a value;

Finally 6.2.6.2/2 implies (I'm pretty sure anyway) that it's not possible to have any combination of value bits that would represent an integer exceeding INT_MAX


To summarise, the possible results of ^ on two ints are:

  • Another valid int value (perhaps with different but non-trapping padding bits to other versions of the same value)
  • A negative zero, which may or may not cause a trap

Solution 4 - C++

Strictly speaking, you can't XOR two integers. You can XOR two integer-sized bags of bits, and you can treat those bags of bits as integers at other times. You can even treat them as integers at all other times.

But at the moment you perform the XOR operation, you're treating them as something quite different from integers, or even numbers, per se: they're just two sequences of bits, where corresponding bits get compared. The concept of overflow doesn't apply to that, and so if you then decide to treat the result as an integer, it cannot overflow either.

Solution 5 - C++

> Is it even possible that XOR will generate such a large integer value that cannot be stored in the int type?

If the operands are int, then no.

> If it is not possible that this can happen then is there a proof for this?

Well, it's trivial from the definition. This is hardly a mathematically rigorous proof, but you could consider that a bit in the output of XOR will only be 1 if one of the operands has 1 in that position. Since an out of range bit cannot be 1 in the operands, there is not output bit with value 1 that is out of range.

Solution 6 - C++

XOR, AND, OR, NOT and any other bitwise operators produce bitwise results, with the bits in the result combined from the bits at exactly the same position in the inputs. So n-bit inputs produce n-bit without any higher bit, so how can it goes off bounds?

Solution 7 - C++

No it cannot. Unlike others answers mine would be mathematical proof.

XOR is shortcut for exclusive or or exclusive disjunction () and can be defined as:

AB = (AB)\(AB)

Your proposition is that

∃x: x ∉ A ∧ x ∉ B ∧ x ∈ (A ⊕ B)

So from first equation

x ∈ (AB)\(AB)

What can be expressed as

x ∈ (AB) ∧ x ∉ (AB)

The second part can be expressed as:

x ∉ A ∧ x ∉ B

The first part can be expressed as:

x ∈ A ∨ x ∈ B

What collide with our assumption that x ∉ A ∧ x ∉ B so proposition is false for any set A and B.

Q.E.D.

Solution 8 - C++

In a GENERAL CASE the described algorithm cannot really find a lonely integer in an array. What it really finds is XOR of all elements that occur odd number times there.

So, if there is just one 'lonely' element there, say an element 'a', and all the other elements occur EVEN number times in the array, then it works 'as required' -> it finds this lonely element 'a'.

Why?

The algorithm carries out XOR of all the elements in the array (a ^ b ^ c ^ d ^ ...)

The XOR operation has the following properties:

  1. a ^ a = 0 (non-equivalence)

  2. a ^ 0 = a (neutrality of 0)

  3. a ^ b = b ^ a (commutative property)

  4. (a ^ b) ^ c = a ^ (b ^ c) (associative property)

Let's assume, for instance, an array with elements: {a, b, c, a, c, b, a, c}

(element 'a' - 3 times, element 'b' - twice, element 'c' - 3 times)

Then, according to the above mentioned XOR properties, the algorithm result

R = (((((((a ^ b) ^ c) ^ a) ^ c) ^ b) ^ a) ^ c)

can be rearranged as follows:

R = (a ^ b) ^ (c ^ a) ^ (c ^ b) ^ (a ^ c) =

= (a ^ a) ^ (b ^ b) ^ (c ^ c) ^ (a ^ c) =

= 0 ^ 0 ^ 0 ^ (a ^ c) = (a ^ c)

i.e.,

a) ...all elements that occur an EVEN number times result in zero

b) ...all elements that occur an ODD number times are XOR-ed and create the final result

XOR is a bit-wise operation, so it never can overflow, of course.

Solution 9 - C++

Suppose

int xor  = x^y;
Max value of int is x = 999999999;
Max value of Xor will come if y=0;
and Max Xor is 999999999;

which is in limit. :)

Solution 10 - C++

> Is it even possible that XOR will generate such a large integer value > that cannot be stored in the int type?

Data-Type3 = Data-Type1 operator Data-Type2

> If it is not possible that this can happen then is there a proof for > this?

We've Data-Type3 in case of Integers is the one out of Data-Type1 and Data-Type2 that has a bigger size, even in case of addition or multiplication.

SIZE(Data-Type3) = MAX(SIZE(Data-Type1), SIZE(Data-Type2))

So if Data-Type1 = Data-Type2 then that's the return-type too.

Short + Short   = Short
Short + Integer = Integer
Short + Long    = Long

Integer + Short   = Integer
Integer + Integer = Integer
Integer + Long    = Long

Long + Short   = Long
Long + Integer = Long
Long + Long    = Long

What can happen is an overflow, which can occur when an operation have a carry. In 2's complement, it's when the carry into the high order column doesn't equal the carry out of the high order column. read more

But XOR operation cannot overflow, because XOR operation does not generate a carry, since XOR is a bit-wise operation like NOT.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionExpert NoviceView Question on Stackoverflow
Solution 1 - C++schnaaderView Answer on Stackoverflow
Solution 2 - C++Mike SeymourView Answer on Stackoverflow
Solution 3 - C++M.MView Answer on Stackoverflow
Solution 4 - C++The SpooniestView Answer on Stackoverflow
Solution 5 - C++eerorikaView Answer on Stackoverflow
Solution 6 - C++phuclvView Answer on Stackoverflow
Solution 7 - C++HaulethView Answer on Stackoverflow
Solution 8 - C++Eric BestView Answer on Stackoverflow
Solution 9 - C++Arun TyagiView Answer on Stackoverflow
Solution 10 - C++Khaled.KView Answer on Stackoverflow