# Endianness and IEEE 754: the bug that sends you back to the datasheet

> Read a 32-bit float register and get absurd numbers: big vs little endian, IEEE 754 decomposition and two's complement. How to decode the bytes correctly.

Published: 2026-06-24
Category: software
Tag: endianness, ieee-754, floating-point, twos-complement, modbus, byte-order, debugging

Page: <https://www.stline.it/en/blog/endianness-ieee754-byte/>

---

One of the most frustrating bugs we hit when integrating third-party instrumentation isn't in an algorithm: it's in four bytes read in the wrong order. The instrument claims to expose a physical quantity as a 32-bit float in a register; we read it and get `1.7e+38`, or `-0.0000000000000000003`, or a clean `NaN`. The true value was `23.7`. Neither side is wrong about the protocol: we just misunderstood each other on *how* those bytes should be reassembled.

## The case

A typical chain: a meter exposes a reading over Modbus, two consecutive 16-bit registers that together form a 32-bit float. Our side reads the registers, concatenates them, interprets them as `float`, and prints a number with no physical meaning. The first reaction, and the wrong one, is to doubt your own parsing algorithm. The right reaction is to drop down to the single-byte level and ask two distinct questions: **in what order do the bytes arrive**, and **how do those bytes encode a number**. These are two independent problems, and when the values read are implausible, rule out byte order before questioning the encoding.

## Endianness: the same number, bytes in a different order

A 32-bit integer or float is four bytes. **Endianness** is the convention for which byte comes first in memory or on the wire. **Big-endian** puts the most significant byte (MSB) first, in the order we'd write the number by hand; **little-endian** puts the least significant (LSB) first. The four bytes `41 BD 70 A4` interpreted big-endian are `23.68`; the same bytes read little-endian, i.e. `A4 70 BD 41`, are a completely different and meaningless float.

Modbus complicates things because it works in big-endian 16-bit registers, but doesn't specify the order *between* the two registers of a 32-bit float. So in practice up to four variants arise — `ABCD`, `CDAB`, `BADC`, `DCBA` — depending on whether the vendor swaps bytes, words, both, or neither (the notorious *word swap*). The datasheet, if well written, tells you which; if badly written, you find out by hand. That's why, faced with absurd numbers, the first move is to systematically try the four byte orders: if one of the permutations returns the expected value, the problem was endianness and not decoding.

## IEEE 754: how bytes become a number

Once the bytes are in the right order, the second problem remains: what they mean. A 32-bit float follows the **IEEE 754** single-precision standard, which splits the 32 bits into three fields: **1 sign bit**, **8 exponent bits** (with a bias of 127), **23 mantissa bits** (with an implicit leading 1). The value is roughly `(-1)^sign · 1.mantissa · 2^(exponent−127)`. Understanding this decomposition is what lets you tell an endianness error from a legitimately small or large value: if the exponent field is all ones you're looking at an infinity or a `NaN`, and almost always that means the bytes are in the wrong order, not that the instrument is broken.

For **integers** the twin trap is the sign. Negative values are encoded in **two's complement**: invert all the bits and add 1. Reading a 16-bit register as unsigned when the instrument intends it signed makes a `-3` show up as `65533` — again an "absurd" number that is really just interpreted with the wrong convention. And as with floats, on a multi-register value the byte order must be resolved *before* applying two's complement.

## The method, not the anecdote

The lesson we carry from this isn't "watch out for Modbus". It's a method: when a numeric value read from a protocol or a register is absurd, drop down to the raw byte and separate the two levels. First, the byte order — big or little, with a possible word swap. Second, the encoding — IEEE 754 for floats, two's complement for signed integers. Resolved in the right order, the number comes back; and almost always the answer was already in the datasheet, in a line we hadn't read on the first pass.

To inspect any four bytes by hand across the different orders and encodings we put a [Data Format Inspector](/en/tools/data-format-inspector/) online; the detail on endianness, IEEE 754 and two's complement is in the [dedicated wiki](/en/wiki/data-format-inspector/).

Integrating instrumentation over Modbus, serial, or a custom binary protocol and the numbers don't add up? [Let's talk](/en/contact/).
