G27
Self-checkedTier 1 13 min readdl.fixed-point-arithmetic

Fixed-point arithmetic and overflow

Adding and subtracting fixed-width numbers: the carry, overflow, sign and zero flags, how to detect overflow, signed and unsigned comparison from the flags, the width of sums and products, and fixed-point fractions (Q formats).

Why it exists

A computer adds numbers in registers of a fixed width, say 8, 32 or 64 bits. The mathematical sum of two nn-bit numbers may need n+1n+1 bits. When that happens, the hardware cannot raise an exception on its own: it keeps the low nn bits and sets flags that describe what happened. The same adder circuit is used for unsigned and for signed (2's complement) numbers, so the flags are the only way software can tell whether the answer is meaningful. Almost every GATE question in this area asks one of three things: what is the result in nn bits, did it overflow (and which kind), or what are the flag values.

Prerequisites

You need the 2's complement system from signed number representation: ranges, negation, and the fact that −x≡2n−x-x \equiv 2^n - x.

Precise definitions

Fixed-width (modular) arithmetic. An nn-bit adder computes (A+B) mod 2n(A + B) \bmod 2^n and a carry bit. The same output bits are the correct result for unsigned operands and for 2's complement operands, provided the true result is within the range of the interpretation.

The four flags. After an addition (or a subtraction, which is addition of the complement) of two nn-bit words AA and BB giving the nn-bit result SS:

  • C (carry): the carry out of the most significant bit.
  • V (overflow): set when the signed result is outside the 2's complement range.
  • N (negative): the sign bit of SS.
  • Z (zero): set when all bits of SS are 0.

Unsigned overflow happens exactly when C=1C = 1 for an addition: the true sum is at least 2n2^n.

Signed overflow for addition happens exactly when V=1V = 1. Three equivalent tests:

  1. The two operands have the same sign and the result has the opposite sign. (Operands of different sign can never overflow when added.)
  2. The carry into the sign bit differs from the carry out of the sign bit: V=cn−1⊕cnV = c_{n-1} \oplus c_n.
  3. The true sum is outside −2n−1…2n−1−1-2^{n-1}\dots 2^{n-1}-1.

For subtraction A−BA - B computed as A+Bˉ+1A + \bar{B} + 1: overflow happens when AA and BB have different signs and the sign of the result differs from the sign of AA.

Carry and borrow in subtraction. Subtraction is done as A+B‾+1A + \overline{B} + 1. The carry out of this addition is 1 exactly when A≥BA \ge B as unsigned numbers, that is, when there is no borrow. So "carry = NOT borrow". Some processors (ARM) keep this carry as C after a subtraction; others (x86) invert it so that the flag means borrow. A GATE question that asks about the flag will state its convention or the machine.

Comparison from the flags (after computing A−BA - B):

TestCondition
A=BA = BZ=1Z = 1
A<BA < B unsignedno carry (with "carry = not borrow")
A≥BA \ge B unsignedcarry
A<BA < B signedN⊕V=1N \oplus V = 1
A≤BA \le B signed(N⊕V)∨Z=1(N \oplus V) \lor Z = 1

The signed tests use N⊕VN \oplus V rather than NN alone because after an overflow the sign bit of the wrapped result is wrong; VV corrects it.

Width rules.

  • The sum of two nn-bit numbers needs at most n+1n + 1 bits. The sum of kk unsigned nn-bit numbers needs at most n+⌈log⁡2k⌉n + \lceil \log_2 k \rceil bits.
  • The product of two nn-bit numbers (signed or unsigned) fits in 2n2n bits. The only product that needs the very top of the signed range is (−2n−1)2=22n−2(-2^{n-1})^2 = 2^{2n-2}, which still fits.
  • Extra (guard) bits above the operands stop overflow in a long chain of additions.

Fixed-point fractions (Q formats). A fixed-point number stores an integer RR and agrees in advance that there are ff bits after the binary point: the value is R/2fR / 2^f. Written Qm.fQm.f for mm integer bits and ff fraction bits (mm includes the sign bit for signed formats). The resolution (distance between neighbouring values) is 2−f2^{-f}. Unsigned Qm.fQm.f covers 00 to 2m−2−f2^m - 2^{-f}; signed covers −2m−1-2^{m-1} to 2m−1−2−f2^{m-1} - 2^{-f}. Addition and subtraction of numbers with the same format is just integer addition on the raw values. Multiplication of Qm.fQm.f by Qm.fQm.f gives a raw product with 2f2f fraction bits (Q2m.2fQ2m.2f); shift right by ff to return to Qm.fQm.f, which may overflow.

How it works

Step through six additions of 8-bit numbers. Each shows the operands, the wrapped sum, the carry out of the sign bit, the carry into it, and the overflow flag VV computed as their exclusive-or. The test file recomputes every value separately.

Fixed-point addition: carry versus overflow: Positive + positive overflows

Computed exactly, not typed

Working

  01100100  (100)
+ 00110010  (50)
= 10010110  carry out 0, carry into sign bit 1

Value, format and bits (changed bits in amber)

Atwos-complement= 100
01100100
Btwos-complement= 50
00110010
A + B, kept in 8 bitstwos-complement= -106
10010110
carry out of the sign bit (C)= 0
carry into the sign bit= 1
overflow V = carry in xor carry out= 1
mathematical sum= 150

Step 1

100 + 50 = 150 is above +127, so the result is not representable. The pattern 1001 0110 reads as -106. The tell-tale is two operands with the same sign and a result of the opposite sign: a carry enters the sign bit but nothing leaves it (carry in 1, carry out 0), so V = 1.

1 / 6
computed by script: exact integer, Fraction and truth-table evaluation (IEEE 754 patterns via Python struct where used), not typed by hand. Python 3.15.1, darwin arm64. python3 scripts/gen-dl-traces.py

The key fact to see in the animation is that carry and overflow are independent. All four combinations occur: (−3+5-3 + 5) has a carry and no overflow, (100+50100 + 50) has overflow and no carry, (−100+−50-100 + -50) has both, and (1+21 + 2) has neither. The carry tells you about the unsigned interpretation, the overflow tells you about the signed one, and the same wrapped bit pattern is the result in both.

Worked examples

EX 1Wrapped sums and flags

Easy

The program below does an 8-bit addition the way a CPU does and prints the flags. The first three lines are rows of the animation.

#include <stdio.h>
#include <stdint.h>
 
/* 8-bit add: returns the wrapped sum and sets the flags the way a CPU does */
static uint8_t add8(uint8_t a, uint8_t b, int *c, int *v, int *n, int *z) {
    unsigned wide = (unsigned)a + b;
    uint8_t s = (uint8_t)wide;
    *c = (int)(wide >> 8);
    *v = (int)((~(a ^ b) & (a ^ s)) >> 7 & 1);
    *n = s >> 7;
    *z = (s == 0);
    return s;
}
 
static void show(int x, int y) {
    int c, v, n, z;
    uint8_t s = add8((uint8_t)x, (uint8_t)y, &c, &v, &n, &z);
    printf("%4d + %4d = %02X  C=%d V=%d N=%d Z=%d\n", x, y, s, c, v, n, z);
}
 
int main(void) {
    show(100, 50);
    show(-100, -50);
    show(-3, 5);
    show(127, 1);
    show(-1, 1);
    int c, v, n, z;
    uint8_t d = add8(5, (uint8_t)(~7u + 1), &c, &v, &n, &z);
    printf("5 - 7: %02X (%d) carry=%d borrow=%d\n", d, (int8_t)d, c, !c);
    d = add8((uint8_t)-100, (uint8_t)(~100u + 1), &c, &v, &n, &z);
    printf("-100 - 100: %02X N=%d V=%d N xor V=%d\n", d, n, v, n ^ v);
    unsigned q = 0x58, r = 0x30;
    unsigned p = q * r;
    printf("Q4.4: %.4f * %.4f = %.4f, raw %X, rescaled %X\n", q / 16.0, r / 16.0, p / 256.0, p, p >> 4);
    return 0;
}

Output:

 100 +   50 = 96  C=0 V=1 N=1 Z=0
-100 +  -50 = 6A  C=1 V=1 N=0 Z=0
  -3 +    5 = 02  C=1 V=0 N=0 Z=0
 127 +    1 = 80  C=0 V=1 N=1 Z=0
  -1 +    1 = 00  C=1 V=0 N=0 Z=1
5 - 7: FE (-2) carry=0 borrow=1
-100 - 100: 38 N=0 V=1 N xor V=1
Q4.4: 5.5000 * 3.0000 = 16.5000, raw 1080, rescaled 108

Reading line 1. 100+50100 + 50: 0110 0100+0011 0010=1001 01100110\,0100 + 0011\,0010 = 1001\,0110 (hex 96), which is −106-106 as a signed byte. Same sign in, different sign out, so V=1V = 1; no carry out of the top bit, so C=0C = 0. As unsigned numbers, 9616=15096_{16} = 150 is the correct sum, so the unsigned interpretation had no overflow.

Reading line 3. −3+5=2-3 + 5 = 2 with C=1C = 1 and V=0V = 0. Signed result is correct. As unsigned this is 253+5=258253 + 5 = 258, which does not fit in 8 bits, and C=1C = 1 says so.

Reading line 5. −1+1=0-1 + 1 = 0: the carry chain runs through every bit, C=1C = 1, Z=1Z = 1, V=0V = 0.

EX 2Subtraction as addition, and carry versus borrow

Medium

Compute 5−75 - 7 in 8 bits. The complement of 7 is 1111 10011111\,1001 (invert 0000 01110000\,0111 to 1111 10001111\,1000, add 1). Add: 0000 0101+1111 1001=1111 11100000\,0101 + 1111\,1001 = 1111\,1110, with no carry out. The result is −2-2 (the program's line 5 - 7: FE (-2) carry=0 borrow=1). Since 5<75 < 7 as unsigned numbers, a borrow was needed. With the "carry = not borrow" convention the carry flag is 0, and an x86-style flag would show the borrow as 1.

EX 3Signed comparison needs N xor V

Medium

Is −100<100-100 < 100 (8-bit signed)? Compute −100−100=−200-100 - 100 = -200, which wraps. The program shows the result 3816=5638_{16} = 56, so N=0N = 0 (the wrapped result looks non-negative), but V=1V = 1. Then N⊕V=1N \oplus V = 1, so the less-than test is true, which is the correct answer. Testing NN alone would give the wrong answer.

EX 4How wide must the sum be?

GATE level

(a) Four 8-bit unsigned numbers are added. The largest total is 4×255=10204 \times 255 = 1020, which needs 10 bits (210=1024>10202^{10} = 1024 > 1020). The rule n+⌈log⁡2k⌉=8+2=10n + \lceil \log_2 k \rceil = 8 + 2 = 10 agrees.

(b) A 1000-element array of 8-bit unsigned values is summed. The maximum total is 255000255000, which needs 18 bits (217=131072<255000≤2182^{17} = 131072 < 255000 \le 2^{18}). The rule gives 8+⌈log⁡21000⌉=8+10=188 + \lceil \log_2 1000 \rceil = 8 + 10 = 18.

EX 5Fixed-point product overflows

GATE level

Unsigned Q4.4Q4.4 numbers have range 00 to 15.937515.9375 and resolution 1/161/16. Take 0x58=5.50x58 = 5.5 and 0x30=3.00x30 = 3.0. The raw product is 0x58×0x30=0x10800x58 \times 0x30 = 0x1080, which has 8 fraction bits (the program prints it as 16.516.5 when divided by 256). To return to Q4.4Q4.4 shift right by 4 to get 0x1080x108, which needs 9 bits. The value 16.516.5 is above 15.937515.9375, so the result overflows the format. Truncating 0x1080x108 to 8 bits would give 0x08=0.50x08 = 0.5, which is wrong.

EX 6Which flag answers which question?

GATE level

Two 8-bit registers hold A=1111 0000A = 1111\,0000 and B=0001 0000B = 0001\,0000.

Unsigned. A=240A = 240, B=16B = 16. A+B=256A + B = 256, so the unsigned sum overflows: the wrapped result is 0000 00000000\,0000 with C=1C = 1.

Signed. A=−16A = -16, B=16B = 16. The sum is 0, which is correct: V=0V = 0 (operands of different sign), and Z=1Z = 1.

The same pair of bit patterns therefore gives an unsigned overflow and no signed overflow.

Cheat box

Cheat box

  • nn-bit adder: result =(A+B) mod 2n= (A + B) \bmod 2^n, plus the carry out CC.
  • Unsigned overflow of an addition: C=1C = 1.
  • Signed overflow of an addition: operands have the same sign and the result has the other sign, or equivalently V=cinto sign⊕cout of signV = c_{\text{into sign}} \oplus c_{\text{out of sign}}.
  • Operands of different signs never overflow when added. For A−BA - B, overflow needs different signs of AA and BB.
  • Subtraction A−B=A+Bˉ+1A - B = A + \bar{B} + 1. Carry out =1= 1 iff A≥BA \ge B unsigned (carry = NOT borrow; x86 stores the borrow).
  • Compare after subtraction: A=BA = B iff ZZ; unsigned A<BA < B iff no carry; signed A<BA < B iff N⊕VN \oplus V.
  • kk numbers of nn bits sum to at most n+⌈log⁡2k⌉n + \lceil \log_2 k \rceil bits. A product of two nn-bit numbers fits in 2n2n bits.
  • Qm.fQm.f: value =raw/2f= \text{raw}/2^f, resolution 2−f2^{-f}. Multiply then shift right by ff.

Traps and GATE patterns

Connections

The adder that produces these flags is built from full adders in adders and subtractors, and the ALU in ALU design exposes them to the program. Booth multiplication computes the 2n2n-bit product of signed numbers. Floating point avoids this choice of a fixed point position at the price of rounding, see IEEE 754.

PYQs

1 previous year question from your book. I re-solved each one myself (1 by running or simulating, 0 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2018 · MCQ · 2 marksQ18 · page 155 of the book
Consider the unsigned 8-bit fixed point binary
Number System below:

b7b6b5b4b3b2b1b0

where the position of the binary point is between
b3 and b2. Assume b7 is the most significant bit
(MSB). Some of the decimal numbers listed below
cannot be represented exactly in the above
representation:

 (i) 31.500 (ii) 0.875 (iii) 12.100 (iv) 3.001

Which one of the following statements is true?
  • (a)None of (i), (ii), (iii), (iv) can be exactly represented.
  • (b)Only (ii) cannot be exactly represented.
  • (c)Only (iii) and (iv) cannot be exactly represented.
  • (d)Only (i) and (ii) cannot be exactly represented.

Self-check

Question 1

In 8-bit 2's complement, compute 0111 0000+0101 00000111\,0000 + 0101\,0000. What are CC and VV?

Show answer

0111 0000=1120111\,0000 = 112 and 0101 0000=800101\,0000 = 80. The sum 192192 is above 127. The wrapped result is 1100 0000=−641100\,0000 = -64. No carry leaves the top bit (112+80=192<256112 + 80 = 192 < 256), so C=0C = 0. Both operands are positive and the result is negative, so V=1V = 1.

Question 2

In 8-bit 2's complement compute 1000 0000+1111 11111000\,0000 + 1111\,1111. What are CC and VV?

Show answer

This is −128+(−1)=−129-128 + (-1) = -129, out of range. Unsigned: 128+255=383128 + 255 = 383, so the carry out is 1 and the result is 383−256=127=0111 1111383 - 256 = 127 = 0111\,1111. The result sign is positive while both operands were negative, so V=1V = 1 and C=1C = 1.

Question 3

How many bits does the sum of three 6-bit unsigned numbers need at most?

Show answer

The maximum is 3×63=1893 \times 63 = 189, which needs 8 bits (27=128≤189<2562^7 = 128 \le 189 < 256). The rule gives 6+⌈log⁡23⌉=86 + \lceil \log_2 3 \rceil = 8.

Question 4

After A−BA - B with 8-bit registers, N=1N = 1 and V=1V = 1. Is A<BA < B in the signed sense?

Show answer

N⊕V=1⊕1=0N \oplus V = 1 \oplus 1 = 0, so A<BA < B is false, which means A≥BA \ge B. The negative-looking result is a wrapped overflow: for example A=100A = 100, B=−100B = -100 gives 200200, which wraps to −56-56 (N=1N = 1) with V=1V = 1, and indeed 100>−100100 > -100.

Revision card

One-screen revision

  • nn-bit add = sum mod 2n2^n plus carry out CC.
  • Unsigned overflow: C=1C = 1 on addition. Signed overflow: same-sign operands, different-sign result, i.e. V=cin⊕coutV = c_{\text{in}} \oplus c_{\text{out}} at the sign bit.
  • Subtract by adding the complement plus 1. Carry out 1 means no borrow.
  • Compare: ZZ for equal, no-carry for unsigned less, N⊕VN \oplus V for signed less.
  • Sum of kk values: n+⌈log⁡2k⌉n + \lceil \log_2 k \rceil bits. Product: 2n2n bits.
  • Qm.fQm.f: raw /2f/ 2^f; multiply, then shift right ff; check the range.

References

  • ·Mano and Ciletti, Digital Design, 5th ed., Chapter 1 (signed binary numbers, arithmetic addition and subtraction, overflow) and Chapter 4 (binary adder-subtractor)
  • ·Hamacher, Vranesic, Zaky, Computer Organization, 5th ed., Chapter 6 Arithmetic (overflow in integer arithmetic)
  • ·Patterson and Hennessy, Computer Organization and Design, Chapter 3 Arithmetic for Computers (addition, subtraction and overflow)

Verification

The animation's carry, overflow and wrapped-sum values are computed by scripts/gen-dl-traces.py and recomputed independently in tests/dl-traces.test.ts. The overflow rules, the signed and unsigned comparison rules from the flags (checked over all 65536 pairs of 8-bit operands), the width rules and the Q-format example are brute-force checked in scripts/enum-checks/dl_numbers.py. The C program is compiled and run by npm run verify:c. The carry-after-subtraction convention is stated for both x86 and ARM from memory and flagged for a textbook check; the independent second pass has not been run yet, so the page stays draft. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (conversions, signed ranges and flags, IEEE 754 fields and custom formats, Boolean identities and counts, K-map groups, adder carries, BCD correction, flip-flop conversions, counter sequences and T equations, state reduction, Quine-McCluskey rounds and covers, floating-point alignment and rounding); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never