Two's-Complement Negation and an Over-Tight Float Tolerance in a Cold-Chain Logger
A cold-chain monitoring product stores each chamber temperature as a signed 16-bit integer in hundredths of a degree Celsius, and each humidity reading as an IEEE-754 binary32 fraction of relative humidity. Two defects surface during release validation. First, a calibration routine that negates every stored temperature to convert between two probe orientations returns -327.68 C unchanged for the cryogenic probe sitting exactly at its documented sensor floor of -327.68 C; every other probe's reading flips sign as intended. Second, a nightly quality gate that flags any humidity reading equal to 0.5 never fires, even though the sensor datasheet states it emits exactly 0.5 during self-test; the stored values are produced by dividing a raw 16-bit ADC count by 65535. The firmware engineer proposes two fixes before the release candidate is frozen on Friday: clamp temperatures to plus or minus 300 C before negation, and retest the gate as abs(h - 0.5) < 0.001. The test lead asks you to review both proposals.
1. Explain why negating the stored -327.68 C reading produces no change, and evaluate the proposed clamp fix.
Read the worked answer
Mechanism. A signed 16-bit integer covers -32768 to 32767. The reading -327.68 C is stored as -32768, which is representable, but its mathematical negation, +32768, is not. The hardware/compiler computes 0 - (-32768) modulo 2^16, which lands back on -32768. So the negation silently returns the input rather than raising an error. This is the classic INT_MIN negation case; the defect is not rounding but range asymmetry.
Why the clamp is the wrong fix.
- -327.68 C is a legitimate reading at the documented sensor floor, not corrupt data. Clamping to -300 C corrupts it by 27.68 C and destroys exactly the excursion evidence the cryo team cares about.
- The clamp also masks the defect: every value in (-327.68, -300] is now silently altered, so the logger loses fidelity in a whole regime to hide a single boundary case.
- The failure mode is a sign error, which can turn a cold excursion into a plausible-looking reading downstream - a compliance problem, not a cosmetic one.
Better options, in order of preference. (1) Widen storage to int32, which changes the wire format and needs a format version bump plus decoder updates on every consumer. (2) Keep int16 but make the negation routine detect INT_MIN and return an explicit saturation flag or error instead of wrapping, so callers must handle it. Given a Friday freeze, ship (2) now and schedule (1).
2. The humidity gate never fires. Is the failure in the comparison operator or in the value being compared, and is the 0.001 tolerance appropriate?
Read the worked answer
0.5 is exactly representable in binary32, so h == 0.5 would work if the pipeline ever produced exactly 0.5. It does not: the value is built as raw / 65535. For the documented self-test ADC count the quotient is a repeating fraction, so the stored value lands near - but not at - 0.5 (for example 32768/65535 = 0.50000763). The defect is in the conversion, not in the operator; a tolerance will hide it, not fix it.
Is 0.001 right? No - it is far too wide.
- Near 0.5, the binary32 spacing (ulp) is about 6e-8. An absolute epsilon of 0.001 is roughly 16,000 ulps.
- On a 0-1 humidity scale, 0.001 is 0.1% of full scale, so the gate fires for any genuine reading in roughly 0.499-0.501, which is ordinary chamber humidity. The result is alarm noise and eventual alarm fatigue, which is worse than a silent gate.
- If a tolerance is used at all, it should be a small multiple of the ulp for the magnitude being compared (order 1e-6 here), not an absolute constant chosen by intuition.
Recommended fix. Compare the integer ADC count to the documented self-test count before the division. Integer equality is exact, immune to float representation, and testable. Better still, have the sensor report self-test as a boolean status field instead of a magic humidity value, so the condition is explicit rather than inferred.
3. With 48 hours to the freeze, how would you rank and scope the two fixes?
Read the worked answer
Rank by consequence, not by ease.
1. Temperature sign error - release-blocking, but not with the proposed patch. A mis-signed reading at the sensor floor can make a cold excursion look like a normal or even warm reading, which defeats the product's purpose and creates a compliance exposure. Ship the guard: detect INT_MIN, refuse to negate, emit an explicit overflow flag, and add a unit test pinning the behaviour. Defer the int32 format change with a tracked migration, because a wire-format change in 48 hours is a larger risk than the defect it removes.
2. Humidity gate - not release-blocking, but ship the corrected version. It is a monitoring miss, not a data-corruption path. The fix is a few lines (compare the integer count, or a properly scaled epsilon), low regression risk, and leaving it as proposed would ship a noisy alarm into production.
Scope discipline. Both changes are small and independently testable, so both can land - but the temperature format change cannot. The judgement the exam is testing is resisting the tempting one-line clamp that makes the symptom disappear while making the data wrong.