Start · Sprachen · JavaScript · Referenz · DataView.prototype.getFloat16()

DataView.prototype.getFloat16()

Methode

Liest 2 Bytes ab <code>byteOffset</code> aus einem <code>DataView</code> und gibt sie als 16-Bit-Gleitkommazahl (IEEE 754 half precision) in Form einer normalen <code>number</code> zurück.

seit JavaScript ES2025 (Baseline 2025: Chrome 135, Firefox 129, Sa Kategorie: method-property

Signatur

DataView.prototype.getFloat16(byteOffset, littleEndian)

Beschreibung

getFloat16() liest zwei Bytes ab der angegebenen Position im zugrunde liegenden ArrayBuffer und interpretiert sie als Gleitkommazahl im Format IEEE 754 binary16 („half precision“): 1 Vorzeichenbit, 5 Exponentenbits, 10 Mantissenbits. Das Ergebnis wird exakt in eine normale JavaScript-number (64-Bit-Double) umgewandelt.

Gebraucht wird die Methode vor allem beim Einlesen binärer Formate, die aus Speicher- oder Bandbreitengründen Half-Floats verwenden, z. B. Vertex-Daten in glTF/WebGL/WebGPU, HDR-Bildformate wie OpenEXR, Gewichte von Machine-Learning-Modellen oder Sensordaten aus Netzwerkprotokollen.

Anders als bei einem Float16Array kannst du mit DataView an beliebigen, auch nicht ausgerichteten Byte-Positionen lesen und die Byte-Reihenfolge (Endianness) pro Aufruf festlegen. Standard ist Big-Endian. Die meisten Dateiformate und praktisch alle aktuellen CPUs nutzen aber Little-Endian, deshalb musst du dort meist true als zweites Argument übergeben.

Parameter

Name Typ Default Beschreibung
$byteOffset Pflicht number Position in Bytes, ab der gelesen wird, gezählt ab dem Anfang der View (nicht des Buffers). Wird in eine ganze Zahl umgewandelt.
$littleEndian boolean false Bei true wird Little-Endian gelesen, bei false oder fehlendem Argument Big-Endian.

Rückgabewert

Typ
number
Beschreibung
Die gelesene 16-Bit-Gleitkommazahl als number, auch Sonderwerte wie Infinity, -Infinity, NaN und -0. Endliche Beträge liegen zwischen etwa 6,0e-8 (kleinster subnormaler Wert) und 65504.

Beispiele

Half-Float in Big- und Little-Endian lesen

const view = new DataView(new ArrayBuffer(2));
// Bytes 0x48 0x42 in den Speicher schreiben
view.setUint8(0, 0x48);
view.setUint8(1, 0x42);

console.log(view.getFloat16(0));       // Big-Endian: 0x4842
console.log(view.getFloat16(0, true)); // Little-Endian: 0x4248
8.515625 3.140625

Präzisionsverlust beim Umweg über Float16

const view = new DataView(new ArrayBuffer(2));
view.setFloat16(0, 0.1, true);

const gelesen = view.getFloat16(0, true);
console.log(gelesen);
console.log(gelesen === Math.f16round(0.1));
0.0999755859375 true

Vertex-Daten aus einem Binärblock parsen (Stride, nicht ausgerichtet)

// Jeder Vertex: 1 Byte Flags + 3 × float16 (x, y, z), also 7 Bytes, Little-Endian
const parseVertices = (buffer) => {
  const view = new DataView(buffer);
  const stride = 7;
  const vertices = [];
  for (let off = 0; off + stride <= view.byteLength; off += stride) {
    vertices.push({
      flags: view.getUint8(off),
      x: view.getFloat16(off + 1, true),
      y: view.getFloat16(off + 3, true),
      z: view.getFloat16(off + 5, true),
    });
  }
  return vertices;
};

// Testdaten erzeugen
const buf = new ArrayBuffer(14);
const w = new DataView(buf);
[[1, 1.5, -2, 0.25], [0, 65504, 0, -0.5]].forEach(([f, x, y, z], i) => {
  const o = i * 7;
  w.setUint8(o, f);
  w.setFloat16(o + 1, x, true);
  w.setFloat16(o + 3, y, true);
  w.setFloat16(o + 5, z, true);
});

console.log(parseVertices(buf));
[ { flags: 1, x: 1.5, y: -2, z: 0.25 }, { flags: 0, x: 65504, y: 0, z: -0.5 } ]

Feature-Erkennung und Bereichsfehler abfangen

const readHalf = (view, offset, le = true) => {
  if (typeof DataView.prototype.getFloat16 !== 'function') {
    throw new Error('getFloat16 wird in dieser Umgebung nicht unterstützt');
  }
  try {
    return view.getFloat16(offset, le);
  } catch (err) {
    if (err instanceof RangeError) return undefined;
    throw err;
  }
};

const view = new DataView(new ArrayBuffer(3));
console.log(readHalf(view, 1)); // Bytes 1–2: gültig
console.log(readHalf(view, 2)); // bräuchte Byte 3: außerhalb
0 undefined

// Wichtig · Fallstricke

  • Endianness: Standard ist Big-Endian. Wer littleEndian weglässt, bekommt bei Little-Endian-Dateiformaten (glTF, EXR, die meisten ML-Formate) falsche Werte, ohne dass ein Fehler geworfen wird.
  • RangeError: Ein Fehler wird geworfen, wenn byteOffset negativ ist oder byteOffset + 2 größer als byteLength der View. Ein TypeError kommt, wenn der Buffer abgetrennt (detached) ist, etwa nach einer Übertragung per postMessage.
  • Genauigkeit: Float16 hat nur rund 3 signifikante Dezimalstellen und einen Maximalwert von 65504. Das Lesen selbst ist verlustfrei, beim Schreiben mit setFloat16() wird aber gerundet. Math.f16round() liefert denselben gerundeten Wert.
  • Kompatibilität: Neu in ES2025 (Chrome/Edge 135, Firefox 129, Safari 18.2, Node.js 24). In älteren Umgebungen fehlt die Methode. Dann prüfst du per Feature-Erkennung und liest ersatzweise mit getUint16() plus manueller Bit-Dekodierung oder nutzt ein Polyfill (z. B. core-js).
  • Leistung: Für große, ausgerichtete Blöcke mit der Byte-Reihenfolge der Plattform ist ein Float16Array meist schneller als viele einzelne getFloat16()-Aufrufe.