Expand/Shrink

floor / round / ceil / trunc

Definition: atom res = floor(atom x)
-- or --
atom res = round(atom x, atom inverted_precision=1)
-- or --
atom res = ceil(atom x)
-- or --
atom res = trunc(atom x)
Description: floor() returns the greatest integer less than or equal to x. (Round down to an integer, towards -infinity.)
round() returns the x rounded to the specified precision.
ceil() returns the smallest integer greater than or equal to x. (Round up to an integer, towards +infinity.)
trunc() returns the integer portion of x. (Round down to an integer, towards 0.)
pwa/p2js: Supported.
Comments: These functions may be applied to an atom or sq_floor(), sq_round(), sq_ceil(), sq_trunc() to all elements of a sequence.
The rules for sequence operations apply.

floor(a/b) is treated specially for performance reasons, as there is no point storing a floating point intermediate/parameter when the fractional part gets discarded immediately. There is a corresponding sq_floor_div() sequence operation to match that performance enhancement, which yields exactly the same results as sq_floor(sq_div()), only faster.

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.

For non-integers, ceil() is one more than floor(), and for integers ceil() returns the same result as floor(), namely the input value unaltered.

The result of ceil() is rounded towards plus infinity. Note that while trunc() rounds towards zero, there is no complimentary builtin function that rounds negative fractions away from zero.

The result of trunc() is always truncated towards zero, whereas floor truncates towards minus infinity.
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:

function precision100(atom x) return bankers_rounding(x*100,100) end function
constant x = {-4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5}
?apply(x,round)             -- {-4,-3,-2,-1,0,1,2,3,4,5}
?apply(x,bankers_rounding)  -- {-4,-4,-2,-2,0,0,2,2,4,4}
?apply(x,precision100)      -- {-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 more likely to match 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 x and the average bankers are both exactly zero, not that it would be difficult to construct a deliberately biased x such that the opposite were true; you only get better outputs for evenly-dispersed/unbiased inputs. Obviously the use of proper knock-on rounding leads to even better results, for instance {0.6,0.6,0.6,0.6,0.6} => {0.6,0.2,0.8,0.4,1.0} (or {0.6,1.2,1.8,2.4,3.0} if you prefer) => {1,0,1,0,1}, guaranteeing that sum(results)==round(sum(inputs)), but there is as yet no builtin routine for that.

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, since obviously there would be no .5s involved in that.
Examples:
?sq_floor({0.5, -1.6, 9.99, 100}) -- {0, -2, 9, 100}
?round(1.4)         -- 1
?round(1.6)         -- 2
?round(8.136,100)   -- 8.14
?ceil(1.4)          -- 2
?ceil(-1.4)         -- -1
?trunc(1.4)         --  1
?floor(1.4)         --  1
?trunc(-1.4)        -- -1
?floor(-1.4)        -- -2
Implementation: floor(): via :%opFloor in builtins\VM\pUnary.e (an autoinclude)
round(), bankers_rounding(), ceil(), trunc(): see builtins\pmaths.e (an autoinclude) for details of the actual implementation.
See Also: apply, remainder
Expand/Shrink