Expand/Shrink

round

Definition: atom x2 = round(atom x1, atom inverted_precision=1)
Description: round x1 to the specified precision.
Comments: The precision is the inverse of what you might have expected, for example:
to round a number to the nearest 0.1, specify an inverted precision of 10,
to round a number to the nearest 1000, specify an inverted precision of 0.001.

This function may be applied to an atom or sq_round() to all elements of a sequence. The rules for sequence operations apply.
Auxillary Function integer pennies = bankers_rounding(atom pence, integer precison=1)

In the standard round() function, exact .5s are rounded up (matching Euphoria) whereas banker’s rounding yields the nearest even number, eg:

constant x1 = {-4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5}
?apply(x1,round)
?apply(x1,bankers_rounding)
function precision100(atom xi) return bankers_rounding(xi*100,100) end function
?apply(x1,precision100)
-- output:
-- {-4,-3,-2,-1,0,1,2,3,4,5}
-- {-4,-4,-2,-2,0,0,2,2,4,4}
-- {-400,-400,-200,-200,0,0,200,200,400,400}

The reason you might want to use banker’s rounding is so that the average of the rounded numbers is as close as possible to the average of the original numbers (ditto total), whereas always rounding up obviously introduces a systemic bias.
Above, the standard rounding average is out by 0.1, whereas the average x1 and the average bankers are both exactly zero (not that it would be difficult to construct a deliberately biased x1 such that the opposite were true; you only get better outputs for evenly-dispersed/unbiased inputs).

Note that this is only possible when working in whole (integer) pennies/cents (and above), not pounds/dollars to 2dp, and the precision is not inverted (see Technicalia). Should you want to store things in 2dp format, that’s fine as long as you round(*100) to get exact whole integer penny/cent values back out when you retrieve them, that is prior to attempting any subsequent calculations that are likely to end up requiring any further banker’s rounding, but of course you don’t need to do that if all you’re going to do is print or add and subtract them. [It should make no difference whatsoever if you use round() or bankers_rounding() to retrieve the whole integer penny/cent values.]
Example:
r = round(1.4)          -- r is 1
r = round(1.6)          -- r is 2
r = round(8.136,100)    -- r is 8.14
Implementation: See builtins\pmaths.e (an autoinclude) for details of the actual implementation.
See Also: apply
Expand/Shrink