JavaScript Float16Array and Half-Precision Floats
The Float16Array proposal introduces native support for
16-bit half-precision floating-point numbers into JavaScript’s typed
array ecosystem. By adding the Float16Array typed array,
Math.f16round(), and corresponding DataView
methods, JavaScript allows developers to efficiently store, process, and
transfer floating-point data using half the memory of standard 32-bit
floats. This feature directly benefits web-based machine learning,
WebGPU graphics pipelines, and large-scale data processing by reducing
memory bandwidth bottlenecks and matching modern hardware
capabilities.
What is Half-Precision (Float16)?
The IEEE 754 standard defines the 16-bit base-2 floating-point format (binary16). It allocates:
- 1 bit for the sign
- 5 bits for the exponent
- 10 bits for the fraction (significand/mantissa)
Compared to standard single-precision (Float32Array, 32
bits) and double-precision (Float64Array or standard
JavaScript numbers, 64 bits), half-precision trades numeric range and
precision for a significantly smaller memory footprint. It supports
values roughly between \(6.10 \times
10^{-5}\) and \(65,504\), with
around 3 to 4 decimal digits of precision.
Core Additions in the Proposal
The ECMAScript Float16Array proposal introduces three
primary components:
1. Float16Array
TypedArray
Like existing typed arrays (Int8Array,
Float32Array), Float16Array provides a view
over an ArrayBuffer where each element occupies exactly 2
bytes (16 bits).
const f16 = new Float16Array([1.5, 2.75, 65504]);
console.log(f16.byteLength); // 6 bytes (3 elements * 2 bytes)When reading from a Float16Array, the 16-bit value is
converted into a standard 64-bit JavaScript number. When writing a
JavaScript number to a Float16Array, the value is rounded
to the nearest representable 16-bit float.
2. Math.f16round()
Similar to Math.fround() for 32-bit floats,
Math.f16round(x) returns the nearest 16-bit half-precision
representation of a number rounded to standard precision.
Math.f16round(1.333); // 1.33300781253. DataView Methods
The proposal extends DataView with methods to read and
write 16-bit floats directly from arbitrary buffer offsets:
DataView.prototype.getFloat16(byteOffset, littleEndian)DataView.prototype.setFloat16(byteOffset, value, littleEndian)
Why Float16 Matters in JavaScript
Machine Learning and AI
Modern deep learning models (such as LLMs and vision transformers)
frequently use FP16 (or BF16) for weights, biases, and activation
tensors. Web-based ML runtimes (such as ONNX Runtime Web or
TensorFlow.js) previously had to emulate FP16 using
Uint16Array or upcast weights to Float32Array,
doubling memory usage. Native Float16Array enables direct
model execution with a 50% memory reduction.
Graphics and WebGPU
GPUs have native hardware support for FP16 calculations and textures.
Using Float16Array allows developers to pass vertex
attributes, HDR color textures, and compute shader buffers directly to
WebGL and WebGPU without CPU-side type conversion or manual bit
packing.
Reduced Memory Bandwidth
In data-intensive applications, memory bandwidth is often the primary performance bottleneck. Storing large arrays in half-precision cuts cache misses and memory traffic in half, resulting in faster data transfer between the CPU, GPU, and Web Workers.