CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-bytebuffer

The swiss army knife for binary data in JavaScript

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

floating-point-operations.mddocs/

Floating Point Operations

Read and write operations for 32-bit and 64-bit floating point numbers with endianness support. These operations provide IEEE 754 compliant floating point I/O capabilities.

Capabilities

32-bit Float Operations

Read and write 32-bit floating point numbers (IEEE 754 single precision).

/**
 * Write 32-bit floating point number (IEEE 754 single precision)
 * @param {number} value - Float value to write
 * @param {number} offset - Offset to write at (default: current offset)
 * @returns {ByteBuffer} This ByteBuffer for chaining
 */
writeFloat32(value, offset);

/**
 * Alias for writeFloat32
 */
writeFloat(value, offset);

/**
 * Read 32-bit floating point number (IEEE 754 single precision)
 * @param {number} offset - Offset to read from (default: current offset)
 * @returns {number|{value: number, offset: number}} Float value or result object
 */
readFloat32(offset);

/**
 * Alias for readFloat32
 */
readFloat(offset);

Usage Examples:

const ByteBuffer = require("bytebuffer");
const bb = ByteBuffer.allocate(16);

// Write 32-bit floats
bb.writeFloat32(3.14159);      // Pi
bb.writeFloat(-42.5);          // Using alias
bb.writeFloat32(1.23e-4);      // Scientific notation
bb.writeFloat32(Infinity);     // Special values supported

// Endianness affects byte order
bb.LE(); // Switch to little endian
bb.writeFloat32(1.5);

bb.BE(); // Switch to big endian
bb.writeFloat32(2.5);

// Read back
bb.flip();
const pi = bb.readFloat32();        // 3.14159 (approximately)
const negative = bb.readFloat();    // -42.5
const scientific = bb.readFloat32(); // 0.000123 (approximately)
const infinite = bb.readFloat32();   // Infinity

// Handle precision limitations
console.log(pi === 3.14159); // May be false due to float precision
console.log(Math.abs(pi - 3.14159) < 0.00001); // Better comparison

64-bit Double Operations

Read and write 64-bit floating point numbers (IEEE 754 double precision).

/**
 * Write 64-bit floating point number (IEEE 754 double precision)
 * @param {number} value - Double value to write
 * @param {number} offset - Offset to write at (default: current offset)
 * @returns {ByteBuffer} This ByteBuffer for chaining
 */
writeFloat64(value, offset);

/**
 * Alias for writeFloat64
 */
writeDouble(value, offset);

/**
 * Read 64-bit floating point number (IEEE 754 double precision)
 * @param {number} offset - Offset to read from (default: current offset)
 * @returns {number|{value: number, offset: number}} Double value or result object
 */
readFloat64(offset);

/**
 * Alias for readFloat64
 */
readDouble(offset);

Usage Examples:

const bb = ByteBuffer.allocate(32);

// Write 64-bit doubles (higher precision than 32-bit floats)
bb.writeFloat64(Math.PI);          // Full precision pi
bb.writeDouble(-123.456789012345); // Using alias
bb.writeFloat64(1.7976931348623157e+308); // Near max double value
bb.writeFloat64(Number.MIN_VALUE); // Smallest positive value

// Special floating point values
bb.writeFloat64(NaN);              // Not a Number
bb.writeFloat64(Infinity);         // Positive infinity
bb.writeFloat64(-Infinity);        // Negative infinity
bb.writeFloat64(-0);               // Negative zero

// Read back
bb.flip();
const precisePi = bb.readFloat64();    // 3.141592653589793
const precise = bb.readDouble();       // -123.456789012345
const largeValue = bb.readFloat64();   // 1.7976931348623157e+308
const minValue = bb.readFloat64();     // 5e-324

// Handle special values
const notANumber = bb.readFloat64();   // NaN
const posInf = bb.readFloat64();       // Infinity
const negInf = bb.readFloat64();       // -Infinity
const negZero = bb.readFloat64();      // -0

// Test for special values
console.log(Number.isNaN(notANumber));    // true
console.log(Number.isFinite(posInf));     // false
console.log(Object.is(negZero, -0));      // true

Precision and Range Considerations

Understanding the differences between 32-bit and 64-bit floating point representations.

32-bit Float (Single Precision):

  • Range: ±1.175494351e-38 to ±3.402823466e+38
  • Precision: ~7 decimal digits
  • Uses 4 bytes of storage

64-bit Double (Double Precision):

  • Range: ±2.2250738585072014e-308 to ±1.7976931348623157e+308
  • Precision: ~15-17 decimal digits
  • Uses 8 bytes of storage

Usage Examples:

const bb = ByteBuffer.allocate(16);

// Demonstrate precision differences
const preciseValue = 1.23456789012345;

// 32-bit float loses precision
bb.writeFloat32(preciseValue);
bb.flip();
const float32Result = bb.readFloat32();
console.log(float32Result); // ~1.2345679 (lost precision)

// 64-bit double maintains precision
bb.clear();
bb.writeFloat64(preciseValue);
bb.flip();
const float64Result = bb.readFloat64();
console.log(float64Result); // 1.23456789012345 (full precision)

// Range demonstration
const veryLarge = 1e200;
bb.clear();

try {
    bb.writeFloat32(veryLarge); // May become Infinity
    bb.flip();
    console.log(bb.readFloat32()); // Infinity
} catch (error) {
    console.log("Value too large for float32");
}

bb.clear();
bb.writeFloat64(veryLarge); // Fits in double
bb.flip();
console.log(bb.readFloat64()); // 1e+200

Endianness and Floating Point

Floating point numbers are affected by endianness settings just like integers.

Usage Examples:

const bb = ByteBuffer.allocate(16);
const testValue = 1.25; // Simple value for testing

// Big endian (default)
bb.BE();
bb.writeFloat32(testValue);
const bigEndianBytes = bb.toHex(0, 4);
console.log("Big endian:", bigEndianBytes);

// Little endian
bb.clear();
bb.LE();
bb.writeFloat32(testValue);
const littleEndianBytes = bb.toHex(0, 4);
console.log("Little endian:", littleEndianBytes);

// The byte order is reversed but the value is the same
bb.flip();
const readValue = bb.readFloat32();
console.log("Read value:", readValue); // Still 1.25

Absolute Positioning

Read and write floats at specific buffer positions without moving the offset.

Usage Examples:

const bb = ByteBuffer.allocate(32);

// Write floats at specific positions
bb.writeFloat32(1.1, 0);    // Position 0
bb.writeFloat32(2.2, 8);    // Position 8
bb.writeFloat64(3.3, 16);   // Position 16

// Read from specific positions
const first = bb.readFloat32(0);   // 1.1
const second = bb.readFloat32(8);  // 2.2
const third = bb.readFloat64(16);  // 3.3

// Offset remains at 0 since we used absolute positioning
console.log(bb.offset); // 0

// Sequential read/write moves the offset
bb.writeFloat32(4.4);  // Writes at current offset (0)
console.log(bb.offset); // 4

Error Handling

Floating point operations may encounter the following error conditions:

  • TypeError: When non-numeric values are provided for float operations
  • Error: When attempting to read beyond buffer limits (if assertions enabled)
  • RangeError: When buffer capacity is insufficient for the operation

Example Error Handling:

const bb = ByteBuffer.allocate(4);

try {
    // This will throw TypeError
    bb.writeFloat32("not a number");
} catch (error) {
    console.error("Invalid value:", error.message);
}

try {
    // This will throw Error if reading beyond buffer
    bb.readFloat64(); // Trying to read 8 bytes from 4-byte buffer
} catch (error) {
    console.error("Read error:", error.message);
}

// Handle special float values
const testValues = [NaN, Infinity, -Infinity, 0, -0];
testValues.forEach(value => {
    bb.clear();
    bb.writeFloat32(value);
    bb.flip();
    const result = bb.readFloat32();
    
    if (Number.isNaN(value)) {
        console.log("NaN preserved:", Number.isNaN(result));
    } else if (!Number.isFinite(value)) {
        console.log("Infinity preserved:", result === value);
    } else if (Object.is(value, -0)) {
        console.log("Negative zero preserved:", Object.is(result, -0));
    }
});

Performance Considerations

  • 32-bit floats use less memory and may have faster I/O on some platforms
  • 64-bit doubles provide higher precision but use twice the storage
  • Endianness conversion may have performance implications on some platforms
  • Absolute positioning avoids offset calculations but requires manual position management

Install with Tessl CLI

npx tessl i tessl/npm-bytebuffer

docs

buffer-conversion.md

buffer-management.md

floating-point-operations.md

index.md

integer-operations.md

string-operations.md

varint-operations.md

tile.json