Skip to main content

Why every healthcare developer should understand binary

from BLE to clinical AI — and why libraries are not enough.

Updated 7 min readMarkdown

“Don’t libraries exist? Why do we need to understand binary?”

This is probably the question that comes to mind after seeing the title. Languages and libraries hide details of binary representation and processing. It is therefore understandable that developers channel their time and resources into high-level programming languages, libraries, frameworks, and API implementation.

It is true that many binary computing operations happening in the background have been abstracted. However, as Joel Spolsky puts it, “All non-trivial abstractions, to some degree, are leaky.” What happens when a numerical representation cannot preserve the precision your application needs? What happens when software reads only one byte of a sensor measurement that occupies two?

These are situations where understanding binary becomes useful. The depth you need depends on what you build. Libraries handle much of the work, but developers still choose representations, connect systems, and check whether the results meet their application’s requirements.

Before I go down the rabbit hole, I will explain certain terms you will come across frequently. A bit is a binary digit with a value of either 0 or 1. Eight bits form a byte. When bit patterns represent integers, the interpretation may be signed or unsigned. A signed integer can be positive, zero, or negative. An unsigned integer can be positive or zero. I will explain other terms as we come across them.

Without further ado, let us start with floating-point numbers. IEEE 754 defines formats and rules for floating-point arithmetic. A binary floating-point format represents a number using a sign, an exponent, and a significand within a fixed number of bits. This limits the range and precision of the values it can store.

For instance, to convert 10.34 to binary manually, we can separate the whole and fractional parts and convert them separately: 10 and 0.34. The whole part, 10, becomes 1010 in binary. For the fractional part, we repeatedly multiply by 2, record the whole-number digit, and continue with the remaining fraction. Let us quickly perform the operation.

Operation

0.34 × 2 = 0.68, 0

0.68 × 2 = 1.36, 1

0.36 × 2 = 0.72, 0

0.72 × 2 = 1.44, 1

0.44 × 2 = 0.88, 0

0.88 × 2 = 1.76, 1

The recorded digits begin 010101. Continuing the calculation gives 10.34 = 1010.010101110000… in binary. The expansion never terminates, so a manual conversion must stop at a chosen precision. This conversion explains the number’s binary expansion; the floating-point format then determines how it is encoded and rounded.

Because the computer allocates only a fixed number of bits to that representation, rounding is inevitable here. Calculations can introduce further rounding, and changing how additions are grouped can change their result. Floating-point addition is not generally associative. These approximations are often acceptable, but the developer needs to check whether they are acceptable for the particular application.

Let us look at a hypothetical application in healthcare: timestamps in software recording an electrocardiogram, or ECG. An ECG records the electrical activity of the heart. Suppose the software samples the waveform every millisecond and stores time since recording began as 32-bit floating-point values, also called float32.

Now suppose a sample is recorded 86,400 seconds after the start: one day. The next sample should have a timestamp of 86,400.001 seconds. Around this magnitude, however, neighbouring float32 values are 0.0078125 seconds apart, or 7.8125 milliseconds. There is no representable float32 value for every one-millisecond step.

Intended timestamp in seconds

Stored float32 timestamp

86400.000

86400.0000000

86400.001

86400.0000000

86400.002

86400.0000000

Under rounding to the nearest representable value, adding float32 values 86,400 and 0.001 produces 86,400. The small increment is rounded away. These results can be reproduced with NumPy; its spacing function reports the distance between neighbouring representable values.

The timestamps now suggest that different samples were recorded at the same instant. Software calculating intervals from these timestamps may obtain zero instead of one millisecond. This demonstrates a timing problem under the stated assumptions; the clinical consequence would depend on how the application uses that information.

Here is where the developer’s understanding matters. A developer might choose float32 to reduce memory usage without recognising the loss of timing resolution over a long recording. The library performs the conversion correctly, but the selected format cannot meet the requirement. The developer can instead preserve timestamps as float64 or use suitably sized integer millisecond ticks. Tests should include long recording durations. Once timestamps have been rounded, displaying more decimal places cannot recover the lost information.

Another practical use case is integrating a Bluetooth Low Energy wearable. Such a device can collect physiological data and transmit it to an application using BLE. The receiving software needs rules that explain how to interpret the measurement bytes.

Consider the standard Bluetooth Heart Rate Service, intended for fitness applications. A measurement starts with a flags byte. Bit 0, the rightmost bit in its usual written representation, indicates whether the heart-rate value occupies one byte or two. A value of 0 selects an unsigned 8-bit integer; 1 selects an unsigned 16-bit integer.

One unsigned byte represents values from 0 to 255. Two represent values from 0 to 65,535. These are encoding limits. The specification recommends one byte for values up to 255 and requires two for larger values. The receiver must follow the flag.

Let us use 300 as a synthetic test value to exercise the two-byte format. The service uses little-endian ordering, so the less significant byte appears first.

The complete value is 44 + (1 × 256) = 300. If the application ignores the flag and reads only the first value byte, it obtains 44. The transmitted bytes may be intact; the interpretation is wrong.

Doesn’t the library handle this? It depends on the library. A device-specific SDK may return an already-decoded heart rate. A general BLE library may deliver the bytes and leave interpretation to application code. SimpleBLE’s heart-rate example includes a separate parsing function. Understanding binary helps the developer check the format, read the correct number of bytes, and test both cases.

Clinical AI introduces another decision about representation. Suppose we want to run an ECG classification model on a device with limited memory. The model’s weights, the numerical values learned during training, might be stored as 32-bit floating-point numbers. Could we represent them using fewer bits?

One approach is quantization: mapping values onto a more limited set of representable values. With 8-bit integer quantization, scale information relates the stored integers to approximate floating-point values. One million weights stored at 32 bits each occupy four million bytes; at 8 bits each, the values occupy one million bytes. This calculation excludes scales, metadata, and other memory requirements.

However, the conversion can change the model’s numerical behaviour. ONNX Runtime’s documentation explains that quantization can reduce accuracy and provides tools for investigating the differences. Successful conversion alone does not establish that the resulting model remains suitable for its intended task.

A developer who understands representation knows to compare the original and converted models using appropriate evaluation data. For a clinical classifier, that includes checking relevant measures such as sensitivity and specificity. If performance changes unacceptably, the team may need a different quantization approach or higher precision for some operations. Storage savings are useful, but acceptable predictive performance must be demonstrated.

Libraries remain valuable throughout these examples. They can handle device communication, numerical operations, and model conversion. Understanding binary helps us recognise the limits of the formats we choose and investigate results that do not meet our requirements. For a healthcare developer, the practical benefit is being able to explain why a timestamp loses detail, why a measurement is decoded incorrectly, or why a converted model needs further evaluation. That knowledge should guide what we build and what we test.

29 views

About the author

  • Healthcare systems engineer. At the forefront of building digital health innovation systems.

No comments yet. Be the first to comment.