Binary long division 2026-10-31
For integers and , an integer division algorithm determines the binary numeral system digits of a quotient by testing and conditionally subtracting successively halved multiples of the divisor. The loop invariant , together with , makes each step a halving of the remaining quotient interval. Start with and large enough that . To decrease by one, subtract from and add to exactly when . Both branches preserve the displayed equality and establish . When , the quotient and remainder conditions hold.
Carry normalization of a digit array 2026-10-31
Process a digit-array integer representation from low to high positions. The integer division supplies and . Replacing the current digit by and adding to the next position preserves the represented value. Append zero storage when a positive carry leaves the allocated array. The processed prefix remains normalized and the value stays fixed.
This also works with signed temporary digits when the represented value is nonnegative. A negative carry cannot leave the final allocated position: the normalized lower digits represent a value less than that position's next radix power, which could not offset that negative carry. Positive carries eventually stop beyond the value's finite radix expansion. Thus the usual nonnegative-digit algorithm admits this useful extension without interpreting truncated division as floor division.
Integer logarithm 2026-10-31
For integers and , the integer logarithm is the largest nonnegative integer such that . Equivalently,The equivalence follows from the monotonicity of exponentiation in its exponent and the definition of the floor function. For example, , so the base-three integer logarithm of is .
A multiplication loop maintains and accepts another factor while . Repeated squaring makes the search faster: precompute starting at , and consider these factors in decreasing . Include a factor when the accumulated product remains at most . If , the loop invariant before considering is . Accepting exactly when halves that uncertainty, proving the greedy algorithm returns . This takes arithmetic operations; it is not the same claim as this bound on bit complexity.
For positive operands in bounded integer arithmetic, test before multiplying by . Integer division makes this equivalent to while preventing integer overflow in a rejected candidate.
Logical right shift 2026-10-24
A logical right shift moves bits toward less significant positions, discards those shifted out, and fills the high positions with zero. On the unsigned interpretation of a machine word, it computes the quotient in integer division by . Indeed, splitting the binary representation after its lowest bits gives with ; the retained upper bits represent . A fixed-width left bit shift by followed by a logical right shift by extracts precisely the low bits, giving the remainder.
With its default argument and a nonnegative integer input, it prints the decimal digits of in order, one per line. For example,
mystery4(407) prints 4, then 0, then 7. Integer division removes the final digit, recursion handles the preceding digits, and the remainder gives the final digit. The function returns None.There is a subtlety for a nondefault base: the recursive call omits
m, so it resets to . For and , the actual output is the decimal digits of , followed by the remainder . For example, mystery4(13, 2) prints 6, then 1, rather than the binary digits of . Passing m on to the recursive call would give a consistent base- positional notation. The interpretation as digits assumes and ; arbitrary integer arguments need not satisfy those conditions.If the prime number divides , then , because is odd. Thus the residue of is an element of the multiplicative group of a finite field , and .
Let be its order of a group element. The integer division writes with . Then , so minimality of gives . Hence divides . Since is a prime number, or . The former would give , which would mean divides , an impossibility. Consequently
In binary long division, first double the divisor until it exceeds
x, then halve it successively. Keep p = 2^j and d = y*p, so no exponentiation is needed inside a loop:q := 0; r := x;
j := 0; p := 1; d := y;
WHILE d <= x DO
d := 2*d;
p := 2*p;
j := j+1
END;
WHILE j > 0 DO
d := d DIV 2;
p := p DIV 2;
j := j-1;
IF r >= d THEN
r := r-d;
q := q+p
END
ENDThe first loop invariant is , , , and . Every doubling preserves it. For integer inputs, after at most iterations when ,
d > x; if , this loop has no iterations. The unbounded increase of proves termination. Equivalently, one can use the decreasing nonnegative loop variant while the guard is true.At the top of the second loop the loop invariant isIt holds on entry because
d > x = r. Suppose the old d is and the old p is . After the three halving assignments, and the old remainder satisfies . If , the desired new bound already holds. Otherwise subtracting leaves and adding to q preserves because . The divisions by two are exact: before each halving, j > 0 makes both p and d even.The loop variant
j decreases by one each iteration. At exit , so d = y and the loop invariant gives the required remainder bound. The work per iteration is constant in the unit-cost model, and the two loops have the same number of iterations. For ,The case , including , takes constant time. These are arithmetic-operation counts with sufficient range for the doubled values; arbitrary-precision arithmetic incurs additional bit complexity. If the inputs were arbitrary positive real numbers, the uniform bound would depend on rather than only ; the stated is the conventional integer division interpretation.Use an auxiliary parser that returns both a value and the unconsumed suffix. The arithmetic helper is:For the integer-valued expression language, this chooses integer division with A number consumes one token. An operator consumes the two successive complete expressions that follow it, so nested operators are handled by recursion. Structural induction on the expression proves that
applyOp :: Op -> Int -> Int -> Int
applyOp Add x y = x + y
applyOp Sub x y = x - y
applyOp Mul x y = x * y
applyOp Div x y = x `div` ydiv's rounding convention. The result is evaluated under the intended arithmetic model; bounded-Int overflow is separate from parsing.evalP :: Polish -> Int
evalP input =
case parse input of
(value, []) -> value
_ -> error "trailing tokens"
where
parse :: Polish -> (Int, Polish)
parse [] = error "missing operand"
parse (Number n : rest) = (n, rest)
parse (Operator op : rest) =
let (left, rest1) = parse rest
(right, rest2) = parse rest1
in (applyOp op left right, rest2)parse consumes exactly its Polish notation and returns its value. Keeping the suffix is essential: neither operand has a fixed token count. Division by zero need not be treated separately under the stated input convention.Use a Scala For example,
object for the singleton pattern, and replace Performance with a version that reports to it. This code plugs into the source's Equipment, GymEquipment, and Functionality definitions; Prediction can remain an independent observer once its displayed string line break is made executable.object GymStandings {
private var scores = Map.empty[GymEquipment, Int]
def record(e: GymEquipment, calories: Int): Unit = {
scores = scores.updated(e, calories)
}
def remove(e: GymEquipment): Unit = {
scores = scores - e
}
def leaders: List[(GymEquipment, Int)] = {
if (scores.isEmpty) Nil
else {
val best = scores.values.max
scores.toList.filter { case (_, score) => score == best }
.sortBy { case (equipment, _) => equipment.name }
}
}
}
class Performance(e: GymEquipment) extends Functionality {
private def calories: Int =
((e.age - e.weight + e.heartRate) * e.time) / 10
e.addFunctionality(this)
GymStandings.record(e, calories)
def update(): Unit = {
val current = calories
GymStandings.record(e, current)
println("Your current performance is: " + current + " calories burned.")
}
}new Performance(treadmill) and new Performance(bike) attach two observers; later GymStandings.leaders returns the leading equipment/score pairs. Initial registration records the equipment's present score, even before its first subsequent update. Recording replaces the same equipment's previous score, so repeated notifications do not multiply its contribution. The explicit remove supports taking an equipment object out of the comparison; detaching its observer when its session ends also prevents later re-registration through another notification. In the original single-threaded event model no extra synchronization is needed.All equipment observers report to the same standings software object, and
leaders returns every maximum or Nil if empty. The query takes to find/filter scores for active equipment objects, plus sorting the tied names for deterministic presentation by name; equal names may remain in either order and still denote distinct equipment. This uses the exact supplied integer score formula and its integer division; it does not substitute a different performance metric. A functioning unsubscribe operation, if required, must explicitly correct the source to _functionalities = _functionalities diff List(f).Let be the maximum positive machine integer. A positive product suffers integer overflow when . The vulnerable expressions are
p*b in part (b), b2[top]*b2[top] in the table guard, and p*b2[k] in the descending search. Even a rejected candidate must be evaluated before its comparison with .The table guard becomes dangerous as soon as its current entry exceeds : approximately for signed 32-bit integers, or for signed 64-bit integers. These are thresholds for the intermediate power, not for alone. For example, with 32-bit arithmetic, and reach the stored power and then try its overflowing square . If , even the initial square may overflow for a tiny . In part (b), the final test can overflow when the next power above exceeds ; at , this already happens for .
For positive operands, integer division gives the exact equivalence . Therefore replace the three guards respectively byand perform each multiplication only after its guard succeeds. Every accepted product is then at most . With these guarded products and sufficient table capacity, the algorithms work throughout , . The stored exponents and weights also fit in those machine ranges. Checking for overflow after multiplying would be too late.
p <= n DIV b
b2[top] <= n DIV b2[top]
p <= n DIV b2[k]For integers not both zero, replace them first by their absolute values, then repeat integer division:
while b != 0:
(a,b) := (b, a mod b)
return aThis is the Euclidean algorithm. Its loop invariant is that equals the original greatest common divisor. When , the new remainder lies in , so is a strictly decreasing nonnegative loop variant. At termination, , proving correctness, including the case where one original input is zero.
Propagate each carry into the next position, lengthening the array if necessary:
procedure Normal(var n: number)
i := 0
while i < len(n) do
carry := floor(n[i] / base)
n[i] := n[i] - carry*base
if carry != 0 then
if i+1 = len(n) then
assert carry > 0
Lengthen(n)
n[i+1] := n[i+1] + carry
i := i+1The integer division identity gives a normalized remainder in . The local rewrite preserves value because a carry at position contributes exactly what was removed at position . The loop invariant is that the represented value is fixed and every position below
i is normalized. Under the stated nonnegative-digit assumption all carries are nonnegative. Carries eventually stop beyond the finite radix expansion of the represented integer; scanning any spare allocated zeros then terminates.This implementation also accepts signed temporary coefficients when their total represented value is nonnegative, using floor division rather than truncation toward zero. A negative carry out of the final position would make the entire represented value negative, since the already normalized lower part is smaller than the next radix power. Thus the assertion cannot fail for a nonnegative represented value. This extended carry normalization of a digit array also makes the arithmetic routines below robust to such temporary representations.
Keep a running product of the fixed base. In particular, The loop invariant is and . Initially the empty product is one. Multiplication by
1.0/n uses floating-point arithmetic, avoiding the truncation that integer division would introduce:def eaLinear(n: Int): Double = {
require(n > 0)
val base = 1.0 + 1.0 / n.toDouble
var k = 0
var result = 1.0
while (k < n) {
result *= base
k += 1
}
result
}base and incrementing k preserve the invariant. The loop variant decreases by one. On exit , so the result is , with exactly multiplications and time complexity. With Double, the operational result is the rounded recurrence, rather than an exact real power; this distinction applies to the next two power computations too.Represent zero by one digit. Since The loop invariant is and ; for positive
int_part is nonnegative, a logical right shift is exactly integer division by two:var digits = 1
var scratch = int_part
while (scratch >= 2) {
scratch = scratch >>> 1
digits += 1
}int_part, also . The loop variant is scratch, strictly decreased whenever the guard holds. On exit, a positive input has , yielding . Therefore digits is the required width, including width one for zero. Shifting avoids an explicit multiplication or division in the code. This uses the supplied assumption that dec.toInt really is the mathematical floor; saturating or invalid conversions are not covered by that assumption.Use the remainder form of the Euclidean algorithm to compute the greatest common divisor, then divide both components of the fraction by it: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
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)
}Int range.Use a
Double base so that the reciprocal is not truncated by integer division. Repeated multiplication gives the requested linear-work approximation to Euler's number.def eaLinear(n: Int): Double = {
require(n > 0)
val base = 1.0 + 1.0 / n.toDouble
var i = 0
var result = 1.0
while (i < n) {
result *= base
i += 1
}
result
}In exact arithmetic over the real numbers, the loop invariant is and . It holds initially, one multiplication establishes the next exponent, and at exit gives the specified power. The nonnegative loop variant is . There are exactly loop multiplications, hence in asymptotic analysis, and one division to form the base. With floating-point arithmetic, the invariant describes the intended exact result; the actual output has the corresponding rounding errors.
A logical right shift by moves into position and fills the high positions with zero. Its unsigned interpretation isMeanwhile the original unsigned interpretation decomposes asBy integer division, , exactly the unsigned quotient. Thus the source instruction puts the required quotient into
r1. This is a proof from binary representation, rather than an assumption that every kind of right shift implements every kind of division. The displayed bit argument applies to , with endpoint operations implemented as a copy or zero where appropriate.Repeated integer division by two generates the binary digits from least significant to most significant. Reverse the accumulated characters once, and treat zero separately.
def binaryCon(n: Int): String = {
require(n >= 0, "n must be nonnegative")
if (n == 0) return "0"
var remaining = n
val digits = new StringBuilder
while (remaining > 0) {
digits.append(if (remaining % 2 == 0) '0' else '1')
remaining /= 2
}
digits.reverse.toString
}Zero produces
"0"; positive inputs produce a binary number without leading zeros. No library routine performs the number-to-base conversion. Appending to the builder and reversing once gives linear work in the number of binary digits and uses that much output storage.