# Rounding Algorithms

FloatType& value ) FloatType result = roundhalfup( std::fabs( value ) );

// round half even (bankers rounding)

// must be included in all copies of the Software, in whole or in part, and

// I havent figured out how to get around the template restrictions yet.)

//————————————————————————–

how much will be deposited and withdrawn.) The important point is that the bankers rounding

I think that this comes with the ceil() function. It rounds up only if the number after the decimal is greater than 0. When you have exactly 0 as decimal it doesnt.

trends, mind you, but you cannot predict

FloatType FloatType roundalternate0(

// the above license grant, this restriction and the following disclaimer,

FloatType& value ) FloatType result = roundhalfdown( std::fabs( value ) );

//————————————————————————–

// (notwithstanding hardware quirks)

FloatType FloatType roundalternate(

(value 0.0) ? -result : result;

FloatType FloatType roundhalfdown0(

FloatType& epsilon = ROUNDING_EPSILON )

// works are solely in the form of machine-executable object code generated by

Of course, the Achilles heel of this method is the random number generator you use. The default pseudorandom generator for C and C++ is not that great. The Mersenne Twister is by far the most popular high-quality pseudorandom number generator, but it is non-trivial to implement so I will not include it below.

// The copyright notices in the Software and this entire statement, including

The one true way to round a number:

You can actually see the bias in the above table: the result tends towards 11 and away from 10.

(value 0.0) ? -result : result;

(value 0.0) ? -result : result;

Let us apply knowledge we all learned in gradeschool: In arithmetic rounding we round up if the next digit is 5 or more, and if it less than 5 we round down. We write ourselves a little function to do just that:

FloatType FloatType roundhalfup0(

// Otherwise use the usual round to closest

// Permission is hereby granted, free of charge, to any person or organization

. We have actually reversed the bias of floor() from negative infinity to positive infinity, because we always choose to round up when exactly halfway between two values:

. It is only unbiased with random data.

RandValue& mid, RandomGenerator& g )

((value -(ipart +0.5)) epsilon)

Given a number exactly halfway between two values, round to the

//————————————————————————–

One very popular method is variously called bankers rounding, round to even, convergent rounding, and even unbiased rounding, to name a few. It works by skewing the bias itself.

Anyway, what follows is a convenient, simple library you are free to use. Ill even permit you to cannabalize it at will (since the algorithms are so obvious…)

//————————————————————————–

FloatType FloatType roundhalfeven(

// do so, all subject to the following:

RandomGenerator FloatType roundrandom(

// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

This was just a simple example that came off the top of my head, but in many sciences and statistical surveys, that difference can mean quite a lot. Suppose that the Apollo missed the moon by 1%? Suppose a pharmaceutical company put too much iron in a daily vitamin pill by 1%? Suppose a construction firm miscalculated the stresses a bridge can take by 1%? In all these scenarios the results would prove deadly. One percent is a

//————————————————————————–

A special case of bias is centered about zero. Let us fix the floor() function to tend towards zero.

The only way to eliminate all bias is to use a

is still biased if the data is biased

FloatType FloatType roundhalfup(

//Named after an equivalent BASIC function.

function doesnt work correctly. If you pass the number 12.5 to the function then you will have as a result 12, but using math it should be 13.

// execute, and transmit the Software, and to prepare derivative works of the

One thing to remember about floating point numbers is that they are not exact. In fact, a lot more can go wrong with them than people realize. So, depending on your hardware and your clibs temperament that second one may or may not be considered the same as the first. IEEE single precision should handle it fine though.

//————————————————————————–

FloatType& value ) FloatType result = std::ceil( std::fabs( value ) );

// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,

// Software, and to permit third-parties to whom the Software is furnished to

-roundhalfeven FloatType ( -value, epsilon ); FloatType ipart; std::modf( value,

// Copyright (c) 2008 Michael Thomas Greer

If I have something wrong let me know. thanks

FloatType& value ) FloatType result = std::floor( std::fabs( value ) );

// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

(value 0.0) ? -result : result;

// Else return the nearest even integer

//—————————————————————————-

// Boost Software License – Version 1.0 – August 17th, 2003

// all derivative works of the Software, unless such copies or derivative

// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

As an unrelated point of interest, if you are passing typed arguments to a template function you dont actually have to give template arguments:

// obtaining a copy of the software and accompanying documentation covered by

//————————————————————————–

For example, the cmath floor() function is biased towards negative infinity, because it always chooses the lower integer number –that is, it always chooses the number closer to negative infinity.

Let us say that the equipment which samples a motorists speed is far more accurate than the computers ability to store it. (This is actually not uncommon.) Again, for simplicity, we will say that the computer stores the speed as integers.

// define a different default epsilon each time you included the file, but

Suppose your local big city and wanted to know how fast people are driving on a particular freeway. The first step is to gather the exact speeds that individual drivers are going, and the second would be to convert all the individual values into a single value that would represent the normal rate of speed. For simplicity here, we will just use the average value.

// to whatever you want it to be. (I wanted to make it so that you could

, or tendancy of the floor() function, to make the numbers closer to negative infinity, thuse skewing the data to an inaccurate number.

//————————————————————————–

// If ipart is even then return ipart

bias… This, of course, is impossible to generate in your typical PC, but it still goes toward solving the problem quite nicely.

// (Either symmetric half-up or half-down will do0

//————————————————————————–

//————————————————————————–

// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT

(*)() ( value, RAND_MAX /2,

A bias is a mathematical notion used in statistics to indicate that samples are not exactly representative of their true values; they are skewed in one way or another.

For random data this is very convenient. Bankers like it because money deposited and withdrawn is random. (There

value (zero is considered even here).

//————————————————————————–

If the city were to simply use the floor() function to convert these to integers, it would get

There are a zillion different ways to round floating point values to integers. C and C++ provide a couple basic ones in math.h or cmath.

// If you want a different default epsilon make sure to change

There are two general categories of rounding algorithm: those that are symmetric about zero and those that are biased in some way.

One solution is called alternate rounding. It works by simply choosing to bias up or down every other time.

// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE

num = 12.5; cout roundhalfdown( num ) endl; num = 12.500001; cout roundhalfdown( num ) endl;

FloatType FloatType roundhalfdown(

I may update it sometime in the future if I can figure out a way around the default epsilon issue. Feel free to make suggestions for improvements.

//————————————————————————–

// this license (the Software) to use, reproduce, display, distribute,

//————————————————————————–

// In this library, symmetric functions are indicated by a zero at the end

//—————————————————————————-

// If value is exctly halfway between two integers

(std::fmod( ipart, 2.0 ) epsilon)

FloatType FloatType roundrandom(

//————————————————————————–

Either way, the sampling is off by about a whole mile per hour. I dont think that the city would actually care about a single mile per hour, but this does illustrate the

The round half down did exactly what it should have. Given a number exactly halfway between two integers (12.5) it rounds