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:

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.3330078125

3. DataView Methods

The proposal extends DataView with methods to read and write 16-bit floats directly from arbitrary buffer offsets:

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.