← Math in Practice
Concept Quantities and representation

Units, dimensions, and conversions

Let the units show whether the calculation can answer the question.

A release artifact is ready, but the upload estimate says 25 seconds and someone expects it to take 3. The file is measured in mebibytes; the network is described in megabits per second. Before choosing which estimate to trust, make the units tell you what is being divided by what.

The judgment to keep

Convert quantities until matching units cancel and the answer has the unit the decision needs. A correct estimate still depends on what the inputs measure.

TypeScriptGo Dimensional analysis · binary and decimal prefixes · transfer time
01 / Read the upload estimate

Two plausible answers differ by more than a rounding error.

A release engineer needs to upload a 240 MiB build artifact through a link described as 80 Mbit/s. One estimate says “about 25 seconds.” A deployment note says “about 3 seconds.” Both numbers are familiar-looking. Neither should be accepted until the dimensions match.

The difference matters operationally. If someone promises a three-second transfer and uses that number for a rollout window, the upload may become the critical path. If the 25-second estimate is treated as a guarantee, the team may miss sharing, retransmission, and processing time. We need an estimate that can be checked and interpreted.

Case file / Release upload Estimate the ideal transfer time before setting the rollout window.
Artifact size
240 MiB, as reported by the build system.
Link rate
80 Mbit/s, a nominal decimal bit rate.
Observed clue
A previous transfer was reported near 31 seconds; its exact byte count and rate source are not yet attached.
Question
What ideal time follows from these inputs, and what should we check if a real transfer takes longer?
Keep: the value, its unit, and what boundary produced it. “240” without MiB and “80” without Mbit/s cannot be safely combined.
02 / Check the dimensions

The units should cancel to the quantity you need.

A dimension describes the kind of quantity: data amount, time, or rate. A unit gives that quantity a scale: byte, bit, second. The transfer question asks for time. The relationship is:

duration = data amount ÷ transfer rate

The file size is in bytes and the rate is in bits per second, so convert the file to bits first. A byte contains 8 bits:

240 MiB × 1,048,576 B/MiB × 8 bit/B ÷ 80,000,000 bit/s
= 2,013,265,920 bit ÷ 80,000,000 bit/s
= 25.165824 s

The unit check is the important part: MiB cancels with MiB, B cancels with B, and bit cancels with bit. Dividing by bit/s is multiplying by s/bit, leaving seconds. If a calculation leaves bytes per second when you need seconds, the conversion is incomplete.

One quantity per step · units shown before arithmetic
StepCalculationResult
Binary size to bytes240 MiB × 2²⁰ B/MiB251,658,240 B
Bytes to bits251,658,240 B × 8 bit/B2,013,265,920 bit
Bits to time2,013,265,920 bit ÷ 80,000,000 bit/s25.165824 s
Checkpoint: before calculating, predict the answer's unit. Here it must be seconds.
03 / Resolve the prefixes

Similar abbreviations can encode different scales and different quantities.

The case uses two distinctions. First, lowercase b means bit and uppercase B means byte; 1 B = 8 bit. Second, SI decimal prefixes and IEC binary prefixes are different: 1 MB = 1,000,000 B, while 1 MiB = 1,048,576 B. The BIPM defines mega as 10⁶; NIST lists mebi as 2²⁰.

So 80 Mbit/s means 80 million bits per second. It does not mean 80 megabytes per second. If the same rate were written as decimal megabytes per second, it would be 10 MB/s, since 80 Mbit/s ÷ 8 = 10 MB/s. For the exact artifact, 240 MiB = 251.65824 MB; dividing that by 10 MB/s again gives 25.165824 s.

01 / SIZEMiB

Binary multiple of bytes: 2²⁰ B per MiB.

02 / RATEMbit/s

Decimal multiple of bits per second: 10⁶ bit/s per Mbit/s.

03 / BRIDGE8 bit/B

Convert the stored bytes to the bits counted by the link rate.

04 / RESULTSeconds

Divide bits by bits per second to leave a duration.

References checked 2026-10-01. The source definitions settle the unit scales; they do not tell us the link's usable throughput.

04 / Compare estimate with evidence

A 31-second upload is a clue about the assumptions, not a root cause.

The ideal estimate is about 25.17 seconds. If the observed transfer took around 31 seconds, that does not show that the arithmetic is wrong. The nominal 80 Mbit/s may not be fully available to this upload; the file may be sent with protocol overhead, retransmitted, or competing with other traffic. There may also be time outside transfer itself, such as connection setup, checksum verification, or storage writes.

The current clue is weak: “around 31 seconds” has no exact start and end events, byte count, or rate source. To distinguish explanations, keep the exact artifact checksum/size and timestamp boundaries, then measure application goodput for an isolated transfer. If goodput is near 80 Mbit/s but wall-clock time is longer, inspect time spent before and after transfer. If it is lower, inspect sharing, retransmission, and the path before changing compression or rollout policy.

Diagnostic pause: which measurement would separate “the link is slower than the nominal rate” from “substantial time is spent outside payload transfer”?
05 / Practice in code

Make the units part of the function contract.

The examples accept a byte count and a bit rate, reject negative sizes and non-positive rates, and return seconds. Each has an explicit MiB-to-byte conversion. Their output is an ideal lower-bound estimate, not observed transfer performance. The Go version uses integer storage for input quantities and floating point for the final duration; very large values may lose some integer precision at that conversion.

Compare the same unit conversion in TypeScript and Go.

Both versions keep the byte-to-bit factor explicit and validate the rate.

TypeScriptIdeal transfer time · dimensions preserved
transfer.ts
/**
 * Estimate an ideal lower-bound transfer time from a byte count and a decimal
 * network rate. Real transfers also spend time on protocol and network effects.
 */
export function estimateTransferSeconds(bytes: number, bitsPerSecond: number): number {
	if (!Number.isSafeInteger(bytes) || bytes < 0) {
		throw new RangeError('bytes must be a non-negative safe integer');
	}
	if (!Number.isSafeInteger(bytes * 8)) {
		throw new RangeError('converted bit count must be a safe integer');
	}
	if (!Number.isFinite(bitsPerSecond) || bitsPerSecond <= 0) {
		throw new RangeError('bitsPerSecond must be a finite, positive number');
	}
	const bits = bytes * 8;
	const seconds = bits / bitsPerSecond;
	if (!Number.isFinite(seconds)) {
		throw new RangeError('estimated duration is outside the supported numeric range');
	}
	return seconds;
}

export function mebibytesToBytes(mebibytes: number): number {
	if (!Number.isFinite(mebibytes) || mebibytes < 0) {
		throw new RangeError('mebibytes must be a finite, non-negative number');
	}
	const bytes = mebibytes * 2 ** 20;
	if (!Number.isSafeInteger(bytes)) {
		throw new RangeError('converted size must be a safe integer number of bytes');
	}
	return bytes;
}

const artifactBytes = mebibytesToBytes(240);
const idealSeconds = estimateTransferSeconds(artifactBytes, 80_000_000);

console.log(`${artifactBytes} B · ${idealSeconds.toFixed(2)} s ideal minimum`);
GoIdeal transfer time · dimensions preserved
transfer.go
package main

import (
	"fmt"
	"math"
)

const bytesPerMebibyte int64 = 1 << 20

// EstimateTransferSeconds returns an ideal lower-bound estimate. The bandwidth
// argument is a decimal bit rate; real transfers include protocol and network effects.
func EstimateTransferSeconds(byteCount int64, bitsPerSecond int64) (float64, error) {
	if byteCount < 0 {
		return 0, fmt.Errorf("byte count must be non-negative")
	}
	if bitsPerSecond <= 0 {
		return 0, fmt.Errorf("bit rate must be positive")
	}
	seconds := float64(byteCount) * 8 / float64(bitsPerSecond)
	if math.IsInf(seconds, 0) || math.IsNaN(seconds) {
		return 0, fmt.Errorf("estimated duration is outside the supported numeric range")
	}
	return seconds, nil
}

func main() {
	const artifactMiB int64 = 240
	artifactBytes := artifactMiB * bytesPerMebibyte
	seconds, err := EstimateTransferSeconds(artifactBytes, 80_000_000)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%d B · %.2f s ideal minimum\n", artifactBytes, seconds)
}
06 / Try a new transfer

Carry the method to another unit label and a boundary case.

Practice / Warm artifact transferA second release needs a planning estimate.
Artifact
750 MB, explicitly decimal: 750,000,000 bytes.
Link rate
100 Mbit/s, explicitly decimal: 100,000,000 bits per second.
Task
Calculate the ideal minimum in seconds. Then explain what an observed 74 seconds could and could not tell you.
Show a worked answer

750,000,000 B × 8 bit/B = 6,000,000,000 bit. Divide by 100,000,000 bit/s to get 60 s. This assumes all nominal bandwidth is available for payload continuously.

An observed 74 seconds is consistent with lower effective throughput or time outside the transfer, but does not distinguish them. Capture bytes and stage timings, then measure payload throughput before recommending a change.

Question to keep: what are the dimensions, which conversion factors cancel, and what does each input actually measure?