cint

cint university / 201 / ced, the cint editor

201-04: division and rounding

This is lesson 201-04 of CU-201.2, checked against cint 0.2.0.

You will split a bill so the parts add up to the cent, and name the rounding rule wherever a result is not a whole number.

the program

// Split a restaurant bill exactly, in cents, with an 18 percent tip.
void main() {
    I64 bill = 10_000;
    I64 tip = muldiv(I64, bill, 18, 100, half_even);
    I64 total = bill + tip;
    I64 people = 3;
    I64 share = total / people;
    I64 left = total % people;
    "bill {bill:/100}, tip {tip:/100}, total {total:/100}\n";
    for p in 1..=people {
        I64 pays = share;
        if (p <= left) { pays += 1; }
        "person {p} pays {pays:/100}\n";
    }
}

Run this program in ced

run it

$ cint run bill.ci
bill 100.00, tip 18.00, total 118.00
person 1 pays 39.34
person 2 pays 39.33
person 3 pays 39.33

The three shares add up to 118.00 exactly. The cent that does not divide evenly goes to the first person, and the program says so in one line.

division in cint

/ rounds toward negative infinity, and % takes the sign of the divisor. Together they keep a == (a / b) * b + a % b for every division that does not fault. This is Python's rule, not C's.

void main() {
    I64 a = -7;
    I64 b = 2;
    "a / b      = {a / b}   a % b      = {a % b}\n";
    "div_trunc  = {div_trunc(a, b)}   rem_trunc  = {rem_trunc(a, b)}\n";
    "div_euclid = {div_euclid(a, b)}   rem_euclid = {rem_euclid(a, b)}\n";
    "floor {div_round(a, b, floor)}  ceil {div_round(a, b, ceil)}  trunc {div_round(a, b, trunc)}  away {div_round(a, b, away)}\n";
    "half_even {div_round(a, b, half_even)}  half_away {div_round(a, b, half_away)}  half_trunc {div_round(a, b, half_trunc)}  half_up {div_round(a, b, half_up)}  half_down {div_round(a, b, half_down)}\n";
}

Run this program in ced

a / b      = -4   a % b      = 1
div_trunc  = -3   rem_trunc  = -1
div_euclid = -4   rem_euclid = 1
floor -4  ceil -3  trunc -3  away -4
half_even -4  half_away -4  half_trunc -3  half_up -3  half_down -4
  • div_trunc and rem_trunc are C's division: toward zero.
  • div_euclid and rem_euclid keep the remainder between 0 and |b| - 1.
  • div_round(a, b, mode) rounds the exact quotient, -3.5 here, by a named mode. There are nine modes. Four round in one direction: floor, ceil, trunc and away. Five round to the nearest integer and differ only on ties: half_even, half_away, half_trunc, half_up and half_down.

Division by zero faults with E_DIV_ZERO. I64.min / -1, whose exact result is one past I64.max, faults with E_OVERFLOW.

muldiv

muldiv(I64, bill, 18, 100, half_even) computes bill * 18 / 100 with the product held exactly, rounds the quotient once by the mode and checks that the result fits I64. Writing bill * 18 / 100 instead would round down and would fault if the product overflows even when the final result fits.

elsewhere

The same division and the same ties were evaluated in other languages on 2026-10-10:

Language -7 / 2 -7 % 2 rounding -3.5 rounding 2.5
cint -4 1 named: half_even gives -4, half_up gives -3 named
C, GCC 13.3 -3 -1 round(-3.5) is -4, rint(-3.5) is -4 round(2.5) is 3, rint(2.5) is 2
Python 3.13 -7 // 2 is -4 1 round(-3.5) is -4 round(2.5) is 2
JavaScript, Node 22.22.0 Math.trunc(-7 / 2) is -3 -1 Math.round(-3.5) is -3 Math.round(2.5) is 3

Python's round rounds ties to even, and JavaScript's Math.round rounds them up. C's round rounds them away from zero, while rint follows a rounding mode set elsewhere in the program, by default to even. None of them names its rule at the call. In cint, a div_round or muldiv call carries the rule.

walk-through

Money in cents. The bill is 10000 cents, an I64. Every amount stays an exact whole number of cents, and the only rounding, the tip's, is named in the call.

{bill:/100} prints a value divided by 100 with two decimal places: 10000 prints as 100.00. Only the printing divides; the value is unchanged.

The leftover cent. total % people is 1, so one person pays one more cent. Any rule for who pays it is fine, as long as the program states it and the shares add up.

try this

  1. Split 100.00 seven ways. How many people pay an extra cent?
  2. Make the tip 15 percent of 99.99. Round it with half_even, then with floor, then with ceil. Which ones differ?

reference

division, rounding modes, muldiv, print formats

Next: 201-05, tests and goldens.