#math/discrete #cs/cp #review #flashcards/cs
## Summary
A binary numeral system where sequential numbers only differ by a single bit. Its useful in hardware, communications, and ML [[genetic algorithms]] for smooth transitions between states. For example if we have a clock and the clock is perfectly between $3(011)$ and $4(100)$ then it possible to have the bits become $7(111)$ which is far. If we use Gray Code, where the [[Hamming Distance]] between adjacent numbers is 1, then the value will either be the previous or the next, but **never** a exception wrong value.
Let $G(i)$ represent the $ith$ number in the Gray Code sequence. In the example below we have $0 \to 1 \to 3$ in decimal, but in gray code this would be $1 \to 2 \to 3$.
$
(00)_{2} \to (01)_{2} \to (11)_{2}
$
## The pattern
Given $G(n)$ notice that the $ith$ bit of $G(n)$ only equals $1$ when $n = b_{i+1}b_{i}\dots = (01) \text{ or } (10)$. And the $ith$ bit of $G(n)$ only equals $0$ when $n = b_{i+1}b_{i}\dots = (11) \text{ or } (00)$
For example:
$
\begin{align}
n &= (110)_{2} \\
g(n) & = (101)_{2} \\
\end{align}
$
%%--%%
With just that logic we can develop the following formula for the $n^{th}$ Gray Code, $G(n)$:
%%?%%
$
G(n) = n \oplus (n \gg 1 )
$
<!--SR:!2026-09-25,133,270-->
%%--%%
### Gray Code: The Effect of Adding 1
Gray code guarantees that $G(n)$ and $G(n+1)$ differ by exactly one bit, calculated via $G(n) = n \oplus (n \gg 1)$. When we add $1$ to $n$, the binary addition behaves in one of two ways.
**Case 1: No Carryover**
If $n$ is even, its least significant bit (LSB) is $0$. Adding $1$ simply flips this LSB to $1$ without affecting higher bits. Because the shifted value $(n \gg 1)$ remains identical in the LSB position, only the LSB flips in the resulting Gray code.
$\begin{align*} G(6) &= 110 \oplus 011 = 101 \\ G(7) &= 111 \oplus 011 = 100 \quad \text{(Only the LSB changed)} \end{align*}$
**Case 2: Carryover**
If $n$ ends in $i$ trailing ones preceded by a zero ($i+1^{th}$ bit), adding $1$ flips those ones to zeros and the preceding zero ($i+1^{th}$ bit) to a one. I.e. $0$ followed by $i$ ones to $1$ followed by $i$ 0s. The first $i$ bits after XOR operation are the same. The $i$ LSBs are preserved.
$(i=2) \qquad \begin{align*} G(3) &= 011 \oplus 001 = 010 \\ G(4) &= 100 \oplus 010 = 110 \quad \text{(Only the 3rd bit changed)} \end{align*}$
**The $(i + 1)^{th}$ Bit Flips**
The $(i + 1)^th$ bit of $n$ goes from a 0 to a 1 when we add $1$ to it.
- If the $i+2^{th}$ bit was a 1 then the XOR for the $i+1^{th}$ bit goes from a 1 to a 0.
- If the $i+2^{th}$ bit was a 0 then the XOR for the $i+1^{th}$ bit goes from a 0 to a 1.
- $a \oplus b \neq \neg a \oplus b$ where $a,b \in \{0,1\}.$
**The $(i+2)^{\text{th}}$ Bit and Beyond are Preserved**
Adding 1 did not effect anything beyond the $i+1^{th}$ bit. So all XORs after $i+1$ are the same.
> [!Insight]
> Case 1 is just case 2 where $i=0$.
## Code
```python
int g (int n) {
return n ^ (n >> 1);
}
```
## Finding the Inverse
Let $N_{k}$ be the $k^{th}$ bit of an integer $N$. Then,
$
\begin{align}
n_{k} &= G(n)_{k} \\
n_{k-1} &= G(n)_{k-1}\oplus n_{k} = G(n)_{k} \oplus G(n)_{k-1}\\
n_{k-2} &= G(n)_{k} \oplus G(n)_{k-1} \oplus G(n)_{k-2}\\
\dots \\
n_{1} &= G(n)_{k} \oplus G(n)_{k-1} \oplus \dots \oplus G(n)_{1}\\
\end{align}
$
```python
# Where g = G(n)
int rev_g (int g) {
int n = 0;
for (; g; g >>= 1)
# Don't confuse bit flips and XOR
# XOR = 1 if bits are diff; 0 if same
n ^= g;
return n;
}
```