Rounding modes
Last updated July 19, 2019
Fastly VCL provides access to various rounding modes by way of independent functions for rounding values. These functions have explicit rounding modes. There is no stateful interface to set a "current" rounding mode.
Fastly VCL does not provide interfaces to round values to a given number of significant figures, to a given multiple, or to a given power.
Tiebreaking when rounding to nearest
The roundoff errors introduced by rounding values to their nearest integers are symmetric, except for treatment of the exact midpoint between adjacent integers.
That is, for every value that gets rounded up (such as 3.77 rounding up to the nearest integer 4.0), there is a corresponding value (3.23) which is rounded down by the same amount. This can be seen visually:
Nearest integer is 3.0 ‹────┤ ├────› Nearest integer is 4.0 3.23 3.24 3.25 3.5 3.75 3.76 3.77 ╸╸╸━━━┷━━━━━┷━━━━━┷━━━╺╺╺ ╸╸╸━━━┷━━━╺╺╺ ╸╸╸━━━┷━━━━━┷━━━━━┷━━━╺╺╺ ╰─────────────────────────┴─────────────────────────╯ Equidistant around 3.5
Rounding to the nearest integer requires a tiebreaking rule for when the fractional part of a value is exactly 0.5. There are several ways to break these ties, enumerated in the "to nearest" rounding modes below.
Overview
Example values:
Input  ceil  floor  trunc  round  roundeven  roundhalfup  roundhalfdown 

1.8  1.0  2.0  1.0  2.0  2.0  2.0  2.0 
1.5  1.0  2.0  1.0  2.0  2.0  1.0  2.0 
1.2  1.0  2.0  1.0  1.0  1.0  1.0  1.0 
0.5  0.0  1.0  0.0  1.0  0.0  0.0  1.0 
0.5  1.0  0.0  0.0  1.0  0.0  1.0  0.0 
1.2  2.0  1.0  1.0  1.0  1.0  1.0  1.0 
1.5  2.0  1.0  1.0  2.0  2.0  2.0  1.0 
1.8  2.0  1.0  1.0  2.0  2.0  2.0  2.0 
A visual representation of the same:
‹── ──› ‹── ──› 1.8 1.5 1.2 0.5 0.5 1.2 1.5 1.8 ╸╸╸━━━┷━━━━━┷━━━━━┷━━╺╺ ╸╸━━┷━━╺╺ ╸╸━━┷━━╺╺ ╸╸━━┷━━━━━━┷━━━━━━┷━━━╺╺╺ "Direct" modes: math.ceil ──› ──› ──› ──› ──› ──› ──› ──› math.floor ‹── ‹── ‹── ‹── ‹── ‹── ‹── ‹── math.trunc ──› ──› ──› ──› ‹── ‹── ‹── ‹── "To nearest" modes: math.round ‹── ‹── ──› ‹── ──› ‹── ──› ──› math.roundeven ‹── ‹── ──› ──› ‹── ‹── ──› ──› math.roundhalfup ‹── ──› ──› ──› ──› ‹── ──› ──› math.roundhalfdown ‹── ‹── ──› ‹── ‹── ‹── ‹── ‹──
"Direct" rounding modes

Round up — math.ceil()
Also known as ceiling, round towards positive infinity
IEEE 754 roundTowardPositive
Noninteger values are rounded up towards +∞. Negative results thus round toward zero.

Round down — math.floor()
Also known as floor, round towards negative infinity
IEEE 754 roundTowardNegative
Noninteger values are rounded down towards ∞. Negative results thus round away from zero.

Round towards zero — math.trunc()
Also known as truncation, round away from infinity
IEEE 754 roundTowardZero
Rounding is performed by removing the fractional part of a number, leaving the integral part unchanged.
NOTE: The
FLOAT
toINTEGER
type conversion in Fastly VCL is not by truncation (as it is in many comparable languages). See discussion under ties away from zero. 
Round away from zero
Also known as round towards infinity
Positive noninteger values are rounded up towards positive infinity. Negative noninteger values are rounded down towards negative infinity.
Not provided in Fastly VCL.
"To nearest" rounding modes
All of the following modes round nontie values to their nearest integer. These modes differ only in their treatment of ties.

Round to nearest, ties away from zero — math.round()
Also known as commercial rounding
IEEE 754 roundTiesToAway
For positive values, ties are rounded up towards positive infinity. For negative values, ties are rounded down towards negative infinity.
This is symmetric behavior, avoiding bias to either positive or negative values. However, this mode does introduce bias away from zero.
This rounding mode is used for implicit
FLOAT
toINTEGER
type conversions in VCL. These behave as if by a call tomath.round()
. 
Round to nearest, ties to even — math.roundeven()
Also known as half to even, convergent rounding, statistician's rounding, Dutch rounding, Gaussian rounding, odd–even rounding, and bankers' rounding
IEEE 754 roundTiesToEven
Of the two nearest integer values, ties are rounded either up or down to whichever value is even.
This rounding mode increases the probability of even numbers relative to odd numbers, but avoids bias to either positive or negative values, and also avoids bias towards or away from zero. The cumulative error is minimized when summing rounded values, especially when the values are predominantly positive or predominantly negative.

Round to nearest, ties towards positive infinity — math.roundhalfup()
Also known as half up
This is asymmetric behavior, where ties for negative values are rounded towards zero, and ties for positive values are rounded away from zero.
WARNING: Some languages use the term half up to mean symmetric behavior. For rounding functions in these languages, "up" is a value of larger absolute magnitude. That is, negative ties will be rounded away from zero, which differs from the behavior in VCL. Take care when porting code using this rounding mode to VCL.

Round to nearest, ties towards negative infinity — math.roundhalfdown()
Also known as half down
This is asymmetric behavior, where ties for negative values are rounded away from zero, and ties for positive values are rounded towards zero.
WARNING: Some languages use the term half down to mean symmetric behavior. For rounding functions in these languages, "down" is a value of smaller absolute magnitude. That is, negative ties will be rounded towards zero, which differs from the behavior in VCL. Take care when porting code using this rounding mode to VCL.

Round to nearest with other tiebreaking schemes
There are several other less common arrangements for tiebreaking. These include ties to odd (in a similar manner as ties to even), random tiebreaking, and stochastic tiebreaking.
These schemes are not provided in Fastly VCL.
Floating point numbers have more computational nuances than are described by the cursory discussion of biases here. For more details, see What every computer scientist should know about floatingpoint arithmetic.
Back to Top