Skip to content
Chif3n
6 min read

Why Standard Floating-Point Arithmetic Kills in Pediatric Dosage: Building a Zero-Loss Decimal Engine

In adult nursing, a 0.05ml rounding error is negligible. In neonatal intensive care, it is fatal. Why JavaScript IEEE 754 floats fail clinical safety checks and how we wrote a deterministic dosage calculator in TypeScript and Python.

When an adult receives IV paracetamol or ampicillin, a rounding variance of 0.05 ml is completely imperceptible.

In a neonatal intensive care unit (NICU) with a premature infant weighing 1.15 kg, that same 0.05 ml variance can represent a 25% overdose of digoxin, dopamine, or gentamycin. A 25% overdose in a neonate triggers cardiac dysrhythmias or acute ototoxicity.

Yet nearly every mobile medical calculator written in JavaScript or Swift naively computes drug infusions using standard 64-bit IEEE 754 double-precision floating-point numbers:

// The infamous JavaScript IEEE 754 floating point drift:
0.1 + 0.2 // => 0.30000000000000004
0.3 - 0.2 // => 0.09999999999999998

When you compound weight-based calculations (mg/kg/dose), reconstitute powder vials into variable diluents (mg/ml), and convert to micro-drip flow rates (60 gtts/ml), floating-point drift creates unpredictable truncation errors.

Here is why standard math breaks down at the bedside, and how we engineered a deterministic, zero-float clinical dosage calculator.


The Three Clinical Formulae That Must Never Drift

1. Weight-Based Daily Dose

Total Daily Dose (mg) = Patient Weight (kg) × Prescribed Rate (mg/kg/day)
Single Dose (mg) = Total Daily Dose / Frequency (doses per day)

2. Reconstituted Syringe Volume

Volume to Draw (ml) = Single Dose (mg) / Stock Concentration (mg/ml)

3. Pediatric Micro-drip Infusion Flow

When administering an IV piggyback over a prescribed time period (minutes), nurses rely on micro-drip chambers where 1 ml = 60 drops (gtt):

Drip Rate (gtt/min) = (Volume in ml × 60 gtt/ml) / Infusion Time in Minutes

Notice that when 60 drops/ml cancels out with 60 minutes in an hour, 1 ml/hr equals exactly 1 micro-drop per minute. Any software that yields fractional drops like 14.333333333333334 gtt/min forces a nurse to guess whether to count 14 or 15 drops by eye on a ticking stopwatch.


The Multi-File Architecture: Safe Dosage Core

The codebase below illustrates our decoupled dosage validation engine. You can toggle between folders to explore the fixed-point scaling math, the pediatric calculation module, the safety interceptor guards, and the verification test harness.

All codes are clickable, scrollable, copyable, and downloadable:

clinical-dosage-coresrc/calculators/pediatricDosing.ts
import { Decimal } from '../math/decimalPrecision';
import { assertDailyDoseSafety } from '../rules/safetyGuards';
 
export interface PediatricPatient {
id: string;
weightKg: number; // e.g. 3.4 kg
ageMonths: number;
}
 
export interface DrugRegimen {
drugName: string;
recommendedMgPerKgPerDay: number; // e.g. 30 mg/kg/day
dosesPerDay: number; // e.g. 3 (every 8 hours)
stockVialMg: number; // e.g. 500 mg vial
diluentVolumeMl: number; // e.g. reconstituted in 10 ml
maxDailyCapMg?: number; // hard ceiling regardless of weight
}
 
export interface DosageResult {
weightKg: number;
totalDailyDoseMg: string;
singleDoseMg: string;
volumeToDrawMl: string;
hourlyDripRateGttMin: number; // integer drops per minute
safetyApproved: boolean;
}
 
/**
* Calculates deterministic pediatric dose with zero float representation drift.
*/
export function calculatePediatricDose(
patient: PediatricPatient,
regimen: DrugRegimen,
infusionMinutes = 60
): DosageResult {
const weight = Decimal.from(patient.weightKg);
const mgPerKg = Decimal.from(regimen.recommendedMgPerKgPerDay);
const frequency = Decimal.from(regimen.dosesPerDay);
 
// 1. Total Daily Dose = weight * mg/kg/day
const totalDailyMg = weight.mul(mgPerKg);
 
// 2. Safety guard check
if (regimen.maxDailyCapMg) {
assertDailyDoseSafety(
regimen.drugName,
totalDailyMg.toNumber(),
regimen.maxDailyCapMg
);
}
 
// 3. Single Dose = total / frequency
const singleDoseMg = totalDailyMg.div(frequency);
 
// 4. Stock concentration = stockVialMg / diluentVolumeMl
const stockMg = Decimal.from(regimen.stockVialMg);
const diluentMl = Decimal.from(regimen.diluentVolumeMl);
const concentrationMgPerMl = stockMg.div(diluentMl);
 
// 5. Volume to draw = singleDoseMg / concentration
const volumeToDrawMl = singleDoseMg.div(concentrationMgPerMl);
 
// 6. Micro-drip flow rate: (volume * 60) / minutes
const microDropFactor = Decimal.from(60);
const duration = Decimal.from(infusionMinutes);
const flowRate = volumeToDrawMl.mul(microDropFactor).div(duration);
 
return {
weightKg: patient.weightKg,
totalDailyDoseMg: totalDailyMg.toFixed(2),
singleDoseMg: singleDoseMg.toFixed(3),
volumeToDrawMl: volumeToDrawMl.toFixed(3),
hourlyDripRateGttMin: Math.round(flowRate.toNumber()),
safetyApproved: true,
};
}

Clinical Lessons from Ward Practice

  1. Never Output Unbounded Floats to Nurses: If an interface presents 0.333333333 ml, an exhausted night-shift nurse is left to guess whether they should draw 0.3 ml or 0.35 ml on an insulin syringe with 0.02 ml gradations.
  2. Fixed-Point Scaling Over Floats: By wrapping calculations in scaled integer arithmetic (BigInt scaling to 6 decimals), we guarantee 100% deterministic reproducibility across Node.js, WebAssembly, and Python backends.
  3. Hard Ceiling Traps: Software should never silently calculate a dosage that exceeds adult toxic limits. When a user accidentally inputs 34 kg instead of 3.4 kg, the system must trip an irreversible clinical stop immediately.
All writing

Comments

Comments coming soon. Set up Giscus on the repo to enable them.