TestBench.tools
GitHub

Fixed-Point Q-Format Converter

Convert real numbers ↔ fixed-point Qm.n representation.

Q0.15 · 16-bit · range -10.999969
resolution 2⁻15 = 3.0518e-5

Raw (hex)
0x4000
Raw (decimal steps)
16384
Stored value
0.5
Quantization error
0.0000e+0

This tool converts real numbers to signed fixed-point Qm.n representation and back — Q15, Q31, Q7.8 or any custom split up to 32 bits. It shows the raw two's-complement word, the value actually stored after rounding, the quantization error, and the format's range and resolution. Reference: 0.5 in Q15 is 0x4000, −1 is 0x8000.

How it works

Fixed-point stores a real number as an integer count of fixed-size steps: raw = round(value × 2ⁿ), decoded as value = raw ÷ 2ⁿ. With m integer bits and one sign bit the representable range is −2ᵐ … 2ᵐ − 2⁻ⁿ at a uniform resolution of 2⁻ⁿ. Unlike floating point, precision is constant across the range and arithmetic maps to plain integer instructions — which is why MCUs without an FPU and deterministic DSP pipelines still run on Q formats.

Values outside the range saturate (clamp) rather than wrap here, matching the saturating arithmetic DSP hardware applies, and the panel flags when that happened.

Worked example

format Q0.15 (16-bit) · value 0.5
raw = round(0.5 × 2¹⁵) = 16384 = 0x4000
−1.0 → −32768 = 0x8000 · 1.0 → clamped to 0x7FFF (max 1 − 2⁻¹⁵)

Converting the other way, or in a format with integer bits, works the same — only the scale factor 2ⁿ changes:

0.75 in Q7.8 → round(0.75 × 2⁸) = 192 = 0x00C0
−0.75 in Q15 → round(−0.75 × 2¹⁵) = −24576 = 0xA000
0xA000 back to real → −24576 ÷ 2¹⁵ = −0.75 (exact, no error)

Common Q formats

Two conventions collide in the wild. Q15 written alone is shorthand for Q0.15 — all fraction, no integer bits — while Q7.8 spells out both halves. Whenever a datasheet or DSP library says just “Q15”, read it as the fractional-only form; the values below all assume the signed layout of 1 sign bit plus m integer and n fraction bits.

ParameterValueNotes
Q0.7 (Q7)8-bit · −1 … 0.9921875step 2⁻⁷ = 0.0078125
Q0.15 (Q15)16-bit · −1 … 0.999969482step 2⁻¹⁵ ≈ 3.05×10⁻⁵
Q1.1416-bit · −2 … 1.999938965step 2⁻¹⁴ ≈ 6.10×10⁻⁵
Q7.816-bit · −128 … 127.99609375step 2⁻⁸ = 0.00390625
Q0.31 (Q31)32-bit · −1 … 1 − 2⁻³¹step 2⁻³¹ ≈ 4.66×10⁻¹⁰

Every row follows from the same two expressions the converter uses: the range is −2ᵐ … 2ᵐ − 2⁻ⁿ and the step size is 2⁻ⁿ. Trading a fraction bit for an integer bit doubles the range and halves the precision — Q7.8 reaches ±128 but resolves only to about four thousandths, where Q15 resolves 128 times finer and cannot leave −1…1.

Parameters

ParameterValueNotes
Layout1 sign + m int + n fractotal ≤ 32 bits
Encoderaw = round(v · 2ⁿ)saturating at range ends
Decodev = raw ÷ 2ⁿ
Range−2ᵐ … 2ᵐ − 2⁻ⁿ
Resolution2⁻ⁿuniform across the range

C implementation

C
#include <stdint.h>

#define Q15(x)  ((int16_t)((x) * 32768.0f))   /* encode at compile time */

/* value = raw / 2^15;  0.5 -> 0x4000, -1.0 -> 0x8000 */
float q15_to_float(int16_t raw) { return raw / 32768.0f; }

int16_t q15_mul(int16_t a, int16_t b)
{
    return (int16_t)(((int32_t)a * b) >> 15);   /* Q15 x Q15 -> Q15 */
}

FAQ

What does Qm.n mean exactly?

A signed fixed-point format with 1 sign bit, m integer bits and n fraction bits (1+m+n bits total). The stored integer counts steps of 2⁻ⁿ: value = raw / 2ⁿ. Q15 is shorthand for Q0.15 — a 16-bit format spanning −1 to 1−2⁻¹⁵, the workhorse of fixed-point DSP.

Why does encoding 1.0 in Q15 give 0x7FFF instead of an exact 1?

Q0.15 cannot represent +1.0: its maximum is 1 − 2⁻¹⁵ ≈ 0.99997. The converter clamps to the nearest representable value and tells you it did — the same saturation a DSP's saturating arithmetic performs.

How large is the quantization error?

At most half a step when rounding: 2⁻ⁿ/2. For Q15 that is about 1.5×10⁻⁵. The converter reports the exact error for your value — stored minus requested.

How do I multiply two Q15 numbers in C?

Multiply as 32-bit integers, then shift right by 15 (with rounding if desired): (int16_t)(((int32_t)a * b) >> 15). The intermediate product is Q30, and the shift renormalizes to Q15 — see the snippet below.

Is my data uploaded?

No. All conversion happens locally in your browser.

Related tools