# stats.weighted-average Sum of value x weight, divided by the sum of the weights: the average price paid over several purchases, a grade point average weighted by credits, a stock's average cost. Everything up to the last step is integer arithmetic, so the only rounding is the one the caller asked for. The exact quotient sum(v x w) x 10^decimals / sum(w) is rounded once by `math.round-div` in the given mode (half-up, half-even, down or up), and the resulting integer is divided by 10^decimals. That last division returns the nearest binary64 to a decimal with at most fifteen significant digits, which is the same double in every language and prints back as exactly that decimal. There is no float accumulation to drift. Values and weights are integers on purpose. Take money in pence and weights in whole units (or scale fractional weights, 0.25 as 25); then the average is exact before it is rounded. Weights of zero are allowed and simply contribute nothing. Negative weights are an error, and so is a list where every weight is zero: there is no average of nothing. The weighted sum, scaled by 10^decimals, must stay within 2^53 - 1 (the range integers share across TypeScript, Python and Rust). Beyond that the capability refuses rather than rounding silently; lower `decimals` or rescale the values. A naive "average of the averages" (15 for one item at 10 and three at 20) is the classic mistake here; the answer is 17.5.