Use the remainder form of the Euclidean algorithm to compute the greatest common divisor, then divide both components of the fraction by it:
def Reduce(num: Int, den: Int): (Int, Int) = {
  require(0 <= num && num < den)
  var a = den
  var b = num
  while (b != 0) {
    val r = a % b
    a = b
    b = r
  }
  (num / a, den / a)
}
The loop invariant is , , and . Initially it holds by symmetry of the greatest common divisor. For , the integer division identity , with , shows that and have exactly the same common integer divisors. Thus the update preserves the loop invariant. The loop variant is the nonnegative integer , which strictly decreases on each iteration. At exit , so . Dividing by preserves the rational number and makes the returned components coprime. In particular, zero is returned as . No multiplication is needed, and all remainders remain within the original nonnegative Int range.
For a positive remaining fraction , the condition is equivalent to . Since decreases as the positive integer increases, choose . The zero fraction needs no term. This is the greedy Egyptian fraction expansion.
The remaining fraction is
The defining inequalities give . Therefore the unreduced new numerator is a nonnegative integer strictly smaller than the old positive numerator. Passing to a reduced fraction can only reduce it further. That numerator is a loop variant, so the process terminates. The increasing denominators are not the termination argument; their size need not be bounded in advance.
Maintain an accumulated array of denominators and an exact remaining fraction. The usual greedy algorithm can require a denominator larger than Int.MaxValue, even for an input with Int components. The following implementation uses arbitrary-precision integers internally. If that representational limit is reached, it returns the always-valid alternative consisting of num copies of . Repeated denominators are permitted by the given Egyptian fraction representation.
def fromRat(num: Int, den: Int): Array[Int] = {
  require(0 <= num && num < den)
  val start = Reduce(num, den)
  var n = BigInt(start._1)
  var d = BigInt(start._2)
  var e = Array.empty[Int]
  while (n > 0) {
    val q = (d + n - 1) / n
    if (!q.isValidInt) return Array.fill(num)(den)
    e = e :+ q.toInt
    val nextN = n * q - d
    val nextD = d * q
    val g = nextN.gcd(nextD)
    n = nextN / g
    d = nextD / g
  }
  e
}
The loop invariant is , , all entries of e are positive, and
Appending and replacing the residual by preserves this equality; division by the greatest common divisor preserves the residual's value. The loop variant is , by the proof in part (b). If nextN is zero, its greatest common divisor with nextD is nextD, giving residual . On normal exit the residual is zero and the returned array has exactly the required value. On the early-return branch, num copies of have that same value directly; the partial greedy Egyptian fraction expansion is discarded. num=0 returns an empty array.
The fallback is a correctness provision for the fixed result type, not an efficiency claim: a large repeated-term array can be impractical. An array of arbitrary-precision integers would retain the greedy Egyptian fraction expansion without this fallback. Allocation, as with any output-producing program, requires enough available memory. The BigInt remainder, greatest common divisor and checked conversion operations are documented in [ref].
An Egyptian fraction need not be proper: several positive unit fractions may sum to at least one. Accordingly, accumulate a general nonnegative reduced fraction, rather than calling the proper-input-only Reduce on every intermediate value. First define an exact helper:
def toRatExact(e: Array[Int]): (BigInt, BigInt) = {
  var n = BigInt(0)
  var d = BigInt(1)
  var i = 0
  while (i < e.length) {
    require(e(i) > 0)
    val x = BigInt(e(i))
    val g = d.gcd(x)
    val nextN = n * (x / g) + d / g
    val nextD = d * (x / g)
    val h = nextN.gcd(nextD)
    n = nextN / h
    d = nextD / h
    i += 1
  }
  (n, d)
}

def toRat(e: Array[Int]): (Int, Int) = {
  val result = toRatExact(e)
  require(result._1.isValidInt && result._2.isValidInt,
          "Reduced result does not fit (Int, Int)")
  (result._1.toInt, result._2.toInt)
}
The loop invariant is , , , , and
Writing , the fraction for the extended prefix has numerator and denominator . These are the nextN and nextD in the code. Reducing them preserves the value and restores coprimality. The loop variant is . At exit the helper returns the exact sum in lowest terms, including for the empty array.
There are three distinct ways to control integer overflow: cancel the common denominator factor before multiplication, reduce after each addition, and use arbitrary-precision arithmetic when the remaining values still exceed fixed-width bounds. Cancellation reduces intermediate size but cannot guarantee that an exact answer fits (Int, Int). For example, the sum is in lowest terms, whose denominator exceeds Int.MaxValue. No implementation returning that fixed type can represent every permitted input exactly. The wrapper therefore checks this unavoidable result-type limitation instead of silently truncating; toRatExact supplies the unrestricted mathematical result.[ref]
Proper fraction 2026-10-31
A nonnegative fraction with positive denominator and numerator smaller than its denominator, so its value lies in . The zero value has the reduced fraction representation . The term is sometimes extended to negative fractions by comparing absolute values; the nonnegative convention is the one used here.
Multiplying numerator and denominator of a fraction by the same nonzero expression can remove a square root from the denominator. For instance,
when and both denominators are nonzero. This uses the difference-of-squares identity . If , the original expression may still be defined even though the rationalized quotient is not, so that case must be handled separately. The related rationalization of a square-root difference applies the same multiplication to a numerator.
Removed compartment 2026-10-14
The removed compartment consists of people permanently excluded from both acquiring and passing on infection in the SIR model. Its count is and its fraction is . Removal can represent regained health with lasting immunity, or another permanent exclusion from acquiring or passing on infection; it need not mean being healthy again. Here there are no deaths. In a variant that counts deaths within , conservation of population would concern the original cohort, rather than the number currently alive.[ref]
For the closed SIR model with , the infectious compartment's fraction approaches . One proof outline uses the bounded, increasing removed compartment's fraction: since , the total time-integrated is finite. The bounded derivative from the SIR model equations prevents indefinitely recurring spikes, so tends to zero.
For , the final size relation for an epidemic follows by dividing the SIR model equations for and while , giving . Integration then yields
This also follows from the SIR first integral and conservation of population. For the stipulated initial value problem, solve
The bisection method gives
About of the original population remains in the susceptible compartment. The is the final removed compartment's fraction, including the initially in the infectious compartment. The newly acquired infection during the modelled period accounts for of the total population, not . Dividing by instead gives the proportion of initially susceptible compartment members who acquire infection; its denominator must be stated.
At the SIR infection peak, the flow into the infectious compartment only balances its outflow; it does not stop. Further infection explains why the final susceptible compartment's fraction is well below . Also for and finite : the closed SIR model does not require everybody to acquire infection before its infectious compartment empties in the long-time limit.
SIR infection peak 2026-10-14
If and , the infectious compartment initially grows. The SIR model equations give its unique later maximum when
Before this SIR infection peak, ; afterward it is negative because the susceptible compartment keeps shrinking. Substituting into the SIR first integral gives
For the stipulated initial value problem,
Thus about of the modelled population belongs to the infectious compartment simultaneously at the SIR infection peak. This is a peak of the infectious compartment, not of incidence, whose flow is . If , the maximum is already at the start and the interior SIR infection peak formula does not apply.
Figure 1. . The SIR model equations produce a SIR infection peak near day . The phase portrait follows decreasing from right to left and changes from growth to decline of the infectious compartment at . The susceptible compartment remains nonempty as approaches zero. The curves use a fourth-order Runge-Kutta method with a fixed step of day; all parameter values are illustrative. Details.
The numerical solution of a differential equation puts the SIR infection peak at about day with , agreeing with the SIR first integral to within . The accompanying generator checks nonnegative fractions and conservation of population without clipping or rescaling. For steps , and day, the largest differences between successive numerical trajectories at shared times are approximately and . Their ratio is , close to the factor expected when a fourth-order Runge-Kutta method's step is halved.
SIR model Created 2026-09-24 Updated 2026-10-14
The SIR model is a mathematical model of an epidemic that follows three groups: a susceptible compartment whose members can acquire infection, an infectious compartment whose members can pass it on, and a removed compartment whose members neither acquire nor pass on infection. The letters stand for susceptible, infectious and recovered or removed. Here we study the simplest closed, constant-parameter version, with homogeneous mixing and no births, deaths, migration or waning immunity. A person who leaves the infectious compartment never returns to the susceptible compartment in this version.[ref]
The appeal of the SIR model is that one can explain a rise and fall in the infectious compartment without changing anyone's behavior: fewer opportunities for new infection eventually reverse the growth. The SIR first integral even determines the SIR infection peak without computing its time. These are useful deductions from explicit assumptions. The stipulated numbers below illustrate the mathematical model; they are neither estimates for an actual disease nor a forecast or medical advice.
Kermack and McKendrick's 1927 paper, "A contribution to the mathematical theory of epidemics", in Proceedings of the Royal Society A, is an early foundation for the SIR model. Its DOI is 10.1098/rspa.1927.0118, also recorded in the Royal Society's archive of contemporary referee reports.[ref][ref]
Figure 1.
Transfers between the three compartments of the SIR model
. The SIR model equations transfer a fraction per day from the susceptible compartment to the infectious compartment, and a fraction per day from the infectious compartment to the removed compartment. Each arrow contributes a loss to one group and an equal gain to another, giving conservation of population. Details.
SIR model equations 2026-10-14
For frequency-dependent transmission, the closed SIR model is a system of ordinary differential equations for the fractions :
Here is the coefficient of frequency-dependent transmission, and is the recovery rate, interpreted more generally as the removal rate. Both have units of inverse time. With a constant recovery rate, the associated individual time in the infectious compartment has an exponential distribution with mean ; the SIR model does not require every person to spend exactly that long there. The fractions themselves have no units.[ref]
For counts , , , the same SIR model equations read
The factor keeps the same in both descriptions. Dropping it while keeping these units would fail dimensional analysis. Some existing SIR model variants use the unnormalized mass-action infection convention instead, including the SIR susceptible-recovered identity; their coefficient is in the notation used here.
Adding the SIR model equations gives , a short proof of conservation of population. Nonnegative starting fractions stay nonnegative: the outflow from either the susceptible compartment or the infectious compartment vanishes when that group is empty, while . Thus the susceptible compartment can only shrink and the removed compartment can only grow.
For a concrete initial value problem, stipulate
At the start, the flow into the infectious compartment is of the total per day, and the flow into the removed compartment is of the total per day. Hence per day. If , these correspond to model rates of and people per day, and net growth people per day. A rate need not be an integer count of events on any particular day.
For this SIR model, the basic reproduction number is
It describes one introduced member of the infectious compartment in an otherwise wholly susceptible compartment. The instantaneous reproduction number at the actual starting state is , obtained by freezing the current conditions and the current susceptible compartment's fraction. More generally it is in this SIR model. The basic reproduction number is a ratio of two rates, so it has no units; is a different quantity, the initial removed compartment's fraction.
While , its instantaneous relative growth is
Initially this equals . Freezing gives the early exponential growth approximation with measured in days. It must fail as the susceptible compartment shrinks. An epidemic invasion threshold occurs at ; if , the deterministic SIR model stays at even above that threshold.
Spreadsheet tabular model 2026-10-14
A spreadsheet tabular model assigns a consistent meaning to each row and column. For an original example, let rows 2–4 describe three items, with quantity in column A, unit price in column B, subtotal in column C, and total including tax in column D. Put the single shared tax rate in F1. The chosen rate is an illustrative assumption. Quantities, unit prices and F1 are inputs; columns C and D hold spreadsheet formulas and display their computed values as outputs.
Enter decimal inputs 2.5, 1.75, 4.5 for the unit prices and 0.2 for the tax rate. The following table expresses those values as exact fractions so that the arithmetic is easy to check. It does not require typing a fraction into an input spreadsheet cell or assume that all software calculates with exact rational numbers.
RowQuantity (A)Unit price (B)Subtotal (C)Total including tax (D)
2
3
4
Start with C2 containing =A2*B2 and D2 containing =C2*(1+$F$1). Here * requests multiplication, and 1+$F$1 adds the tax fraction to one. Copy these two spreadsheet formulas down into rows 3 and 4, a fill operation. The relative spreadsheet references change with the destination row: C3 becomes =A3*B3 and D3 becomes =C3*(1+$F$1); C4 becomes =A4*B4 and D4 becomes =C4*(1+$F$1). The absolute spreadsheet reference $F$1 continues to read the shared rate. Copying spreadsheet formulas adjusts relative coordinates while retaining absolute coordinates. [ref]
Figure 1.
Original three-row spreadsheet tabular model before and after filling two spreadsheet formulas, with a shared absolute spreadsheet reference
. Details.
The same mathematical expression applies to every item. Writing for quantity, for unit price and for the shared tax rate gives
For row 2, the exact arithmetic is . The subtotals add to , so the totals add to , agreeing with . The spreadsheet formulas encode the relationship; the displayed numbers are its results for these particular inputs.
This separation is useful for forecasting and sensitivity analysis. Keeping quantities and unit prices fixed while changing only F1 from to gives exact totals , , and . More generally, a rate change changes each total by
This follows by expanding the two mathematical expressions and cancelling . Here , so the increases are , , and , adding to . One shared input makes the assumption visible and consistent across all rows. Overwriting a computed total with a number would instead remove that spreadsheet formula; its value would cease to follow the model when the rate changes.
// Target: computer-science.bigb
Susceptible compartment Created 2026-10-14 Updated 2026-10-31
The susceptible compartment consists of people who can acquire infection. In the closed SIR model, is their count and their fraction of the fixed total . Membership expresses the assumptions of the mathematical model, rather than measuring the strength of an individual's immunity.
Unit fraction Created 2026-10-20 Updated 2026-10-31
A fraction of the form for a positive integer . Its numerator is 1 and its denominator determines it uniquely.