Sunteți pe pagina 1din 14

6/25/2015

HowToImplementCustomRoundingProcedures

Support

How To Implement Custom


Rounding Procedures
This article was previously published under Q196652

SUMMARY
There are a number of different rounding algorithms available in Microsoft products. Rounding
algorithms range from Arithmetic Rounding in Excel's Worksheet Round function to Banker's
Rounding in the CInt, CLng, and Round functions in Visual Basic for Applications. This article
describes what the various Visual Basic for Applications rounding functions do and provides
samples of using the functions. In addition, the article includes sample functions that implement
various rounding algorithms.

MORE INFORMATION
Rounding Explained
You need to round when you want to convert a number of greater precision into a number of
lesser precision. The most common case is when you need to convert a floatingpoint number
into an integer.

https://support.microsoft.com/enus/kb/196652

1/14

6/25/2015

HowToImplementCustomRoundingProcedures

Rounding Down
The simplest form of rounding is truncation. Any digits after the desired precision are simply
ignored. The VBA Fix function is an example of truncation. For example, Fix3.5 is 3, and
Fix3.5 is 3.
The Int function rounds down to the highest integer less than the value. Both Int and Fix act
the same way with positive numbers truncating but give different results for negative
numbers: Int3.5 gives 4.
The Fix function is an example of symmetric rounding because it affects the magnitude
absolute value of positive and negative numbers in the same way. The Int function is an
example of asymmetric rounding because it affects the magnitude of positive and negative
numbers differently.
Excel has similar spreadsheet functions: Int, Floor, and RoundDown. Int works the same way
as Int does in Visual Basic for Applications. Floor truncates positive values, but does not work
with negative numbers. The RoundDown function works the same way as the VBA Fix function.
Microsoft SQL Server has a Round function that can act like the VBA Fix function. SQL Server
also has a Floor function, which works the same way as VBA Int function.

Rounding Up
SQL Server and Excel both have a function called Ceiling, which always rounds fraction values up
more positive to the next value.
Visual Basic for Applications does not have a corresponding roundup function. However, for
negative numbers, both Fix and Int can be used to round upward, in different ways.
Fix rounds towards 0 up in the absolute sense, but down in terms of absolute magnitude.
Fix3.5 is 3.5.
Int rounds away from 0 up in terms of absolute magnitude, but down in the absolute sense.
Int3.5 is 4.

Arithmetic Rounding
When rounding always down or up, the resulting number is not necessarily the closest to the
original number. For example, if you round 1.9 down to 1, the difference is a lot larger than if you
round it up to 2. It is easy to see that numbers from 1.6 to 2.4 should be rounded to 2.
However, what about 1.5, which is equidistant between 1 and 2? By convention, the halfway
number is rounded up.
https://support.microsoft.com/enus/kb/196652

2/14

6/25/2015

HowToImplementCustomRoundingProcedures

You can implement rounding halfway numbers in a symmetric fashion, such that .5 is rounded
down to 1, or in an asymmetric fashion, where .5 is rounded up to 0.

Pageissafe

InternetSecurity2015

The following functions provide symmetric arithmetic rounding:


The Excel Round spreadsheet function.
The SQL Server Round function can do symmetric arithmetic rounding.
The following function provide asymmetric arithmetic rounding:
The Round method of the Java Math library.
Visual Basic for Applications does not have any function that does arithmetic rounding.

Banker's Rounding
When you add rounded values together, always rounding .5 in the same direction results in a bias
that grows with the more numbers you add together. One way to minimize the bias is with
banker's rounding.
Banker's rounding rounds .5 up sometimes and down sometimes. The convention is to round to
the nearest even number, so that both 1.5 and 2.5 round to 2, and 3.5 and 4.5 both round to 4.
Banker's rounding is symmetric.
In Visual Basic for Applications, the following numeric functions perform banker's rounding:
CByte, CInt, CLng, CCur, and Round.
There are no Excel spreadsheet functions that perform banker's rounding.

Random Rounding
Even banker's rounding can bias totals. You can take an extra step to remove bias by rounding .5
up or down in a truly random fashion. This way, even if the data is deliberately biased, bias might
be minimized. However, using random rounding with randomly distributed data might result in a
larger bias than banker's rounding. Random rounding could result in two different totals on the
same data.
No Microsoft products implement any sort of random rounding procedure.

Alternate Rounding
Alternate rounding is rounding between .5 up and .5 down on successive calls.
No Microsoft products implement an alternate rounding procedure.
https://support.microsoft.com/enus/kb/196652

3/14

6/25/2015

HowToImplementCustomRoundingProcedures

The Round() Function is Inconsistently Implemented


The Round function is not implemented in a consistent fashion among different Microsoft
products for historical reasons.
The following table relates product to implementation:

ProductImplementation

VisualBasicforApplications6.0Banker'sRounding
ExcelWorksheetSymmetricArithmeticRounding
SQLServerEitherSymmetricArithmeticRou
nding
orSymmetricRoundDown(Fix)
dependingonarguments
JavaMathlibraryAsymmetricArithmeticRounding

The Round function in Visual Basic 6.0 and Visual Basic for Applications 6.0 performs banker's
rounding. It has an optional second argument that specifies the number of decimal digits to
round to:

Debug.PrintRound(2.45,1)returns2.4.

Sample Data
The following table shows some sample data and the effects of various rounding methods on the
numbers and totals generated.

Number/Int./Fix/Ceiling/Asym.Arith./Sym.Arith./Banker's/Random/Al
t.

https://support.microsoft.com/enus/kb/196652

4/14

6/25/2015

HowToImplementCustomRoundingProcedures

2.632233333
2.532223223
2.432222222
1.621122222
1.521112211
1.421111111
0.610011111
0.510001011
0.410000000
0.400100000
0.500111011
0.600111111
1.411211111
1.511222211
1.611222222
2.422322222
2.522333233
2.622333333

Total of all numbers:

Number/Int./Fix/Ceiling/Asym.Arith./Sym.Arith./Banker's/Random/Al
t.

0.090930010

Total of all negative numbers:

Number/Int./Fix/Ceiling/Asym.Arith./Sym.Arith./Banker's/Random/Al
t.

13.51899121513131
4

https://support.microsoft.com/enus/kb/196652

5/14

6/25/2015

HowToImplementCustomRoundingProcedures

Total of all positive numbers:

Number/Int./Fix/Ceiling/Asym.Arith./Sym.Arith./Banker's/Random/Al
t.

13.599181515131414

The table shows the difference between the various rounding methods. For randomly distributed
positive and negative numbers, Fix, symmetric arithmetic rounding, banker's rounding, and
alternating rounding provide the least difference from actual totals, with random rounding not
far behind.
However, if the numbers are either all positive or all negative, banker's rounding, alternating
rounding, and random rounding provide the least difference from the actual totals.

Sample User-Defined Rounding Functions


The sample code in the following Function Listing section provides sample implementations for
each of the rounding types described.
The functions provided are:

AsymDownAsymmetricallyroundsnumbersdownsimilartoInt()
.
Negativenumbersgetmorenegative.
SymDownSymmetricallyroundsnumbersdownsimilartoFix().
Truncatesallnumberstoward0.
SameasAsymDownforpositivenumbers.
AsymUpAsymmetricallyroundsnumbersfractionsup.
SameasSymDownfornegativenumbers.
SimilartoCeiling.
SymUpSymmetricallyroundsfractionsupthatis,awayfro
m0.
SameasAsymUpforpositivenumbers.
SameasAsymDownfornegativenumbers.
https://support.microsoft.com/enus/kb/196652

6/14

6/25/2015

HowToImplementCustomRoundingProcedures

AsymArithAsymmetricarithmeticroundingrounds.5upalways.
SimilartoJavaworksheetRoundfunction.
SymArithSymmetricarithmeticroundingrounds.5awayfrom0
.
SameasAsymArithforpositivenumbers.
SimilartoExcelWorksheetRoundfunction.
BRoundBanker'srounding.
Rounds.5upordowntoachieveanevennumber.
Symmetricalbydefinition.
RandRoundRandomrounding.
Rounds.5upordowninarandomfashion.
AltRoundAlternatingrounding.
Alternatesbetweenrounding.5upordown.
ATruncDigitsSameasAsyncTruncbuttakesdifferentarguments.

All of these functions take two arguments: the number to be rounded and an optional factor. If
the factor is omitted, then the functions return an integer created by one of the above methods.
If the factor is specified, the number is scaled by the factor to create different rounding effects.
For example AsymArith2.55, 10 produces 2.6, that is, it rounds to 1/factor = 1/10 = 0.1.
NOTE: A factor of 0 generates a runtime error: 1/factor = 1/0.
The following table shows the effects of various factors:

ExpressionResultComment

AsymArith(2.5)3Roundsuptonextinteger.
BRound(2.18,20)2.2Roundstothenearest5cents(1/20dollar
).
SymDown(25,.1)20Roundsdowntoanevenmultipleof10.

The exception to the above description is ADownDigits, which is a template function that allows
you to specify the number of decimal digits instead of a factor.
https://support.microsoft.com/enus/kb/196652

7/14

6/25/2015

HowToImplementCustomRoundingProcedures

ExpressionResultComment

ADownDigits(2.18,1)2.1Roundsdowntonextmultipleof10^
1.

Function Listing

FunctionAsymDown(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
AsymDown=Int(X*Factor)/Factor
EndFunction
FunctionSymDown(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
SymDown=Fix(X*Factor)/Factor
'Alternately:
'SymDown=AsymDown(Abs(X),Factor)*Sgn(X)
EndFunction
FunctionAsymUp(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
DimTempAsDouble
Temp=Int(X*Factor)
AsymUp=(Temp+IIf(X=Temp,0,1))/Factor
EndFunction
FunctionSymUp(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
DimTempAsDouble
Temp=Fix(X*Factor)
SymUp=(Temp+IIf(X=Temp,0,Sgn(X)))/Factor
EndFunction
FunctionAsymArith(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
AsymArith=Int(X*Factor+0.5)/Factor
https://support.microsoft.com/enus/kb/196652

8/14

6/25/2015

HowToImplementCustomRoundingProcedures

EndFunction
FunctionSymArith(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
SymArith=Fix(X*Factor+0.5*Sgn(X))/Factor
'Alternately:
'SymArith=Abs(AsymArith(X,Factor))*Sgn(X)
EndFunction
FunctionBRound(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
'Forsmallernumbers:
'BRound=CLng(X*Factor)/Factor
DimTempAsDouble,FixTempAsDouble
Temp=X*Factor
FixTemp=Fix(Temp+0.5*Sgn(X))
'Handleroundingof.5inaspecialmanner
IfTempInt(Temp)=0.5Then
IfFixTemp/2<>Int(FixTemp/2)Then'IsTempodd
'ReduceMagnitudeby1tomakeeven
FixTemp=FixTempSgn(X)
EndIf
EndIf
BRound=FixTemp/Factor
EndFunction
FunctionRandRound(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
'ShouldExecuteRandomizestatementsomewherepriortocalling.
DimTempAsDouble,FixTempAsDouble
Temp=X*Factor
FixTemp=Fix(Temp+0.5*Sgn(X))
'Handleroundingof.5inaspecialmanner.
IfTempInt(Temp)=0.5Then
'ReduceMagnitudeby1inhalfthecases.
FixTemp=FixTempInt(Rnd*2)*Sgn(X)
EndIf
RandRound=FixTemp/Factor
EndFunction
FunctionAltRound(ByValXAsDouble,_
OptionalByValFactorAsDouble=1)AsDouble
StaticfReduceAsBoolean
DimTempAsDouble,FixTempAsDouble
Temp=X*Factor
FixTemp=Fix(Temp+0.5*Sgn(X))
'Handleroundingof.5inaspecialmanner.
IfTempInt(Temp)=0.5Then
https://support.microsoft.com/enus/kb/196652

9/14

6/25/2015

HowToImplementCustomRoundingProcedures

'Alternatebetweenrounding.5down(negative)andup(positiv
e).
If(fReduceAndSgn(X)=1)Or(NotfReduceAndSgn(X)=1)Th
en
'Or,replacethepreviousIfstatementwiththefollowingto
'alternatebetweenrounding.5toreducemagnitudeandincreas
e
'magnitude.
'IffReduceThen
FixTemp=FixTempSgn(X)
EndIf
fReduce=NotfReduce
EndIf
AltRound=FixTemp/Factor
EndFunction
FunctionADownDigits(ByValXAsDouble,_
OptionalByValDigitsAsInteger=0)AsDouble
ADownDigits=AsymDown(X,10^Digits)
EndFunction

NOTE: With the exception of Excel's MRound worksheet function, the built in rounding
functions take arguments in the manner of ADownDigits, where the second argument specifies
the number of digits instead of a factor.
The rounding implementations presented here use a factor, like MRound, which is more flexible
because you do not have to round to a power of 10. You can write wrapper functions in the
manner of ADownDigits.

Floating Point Limitations


All of the rounding implementations presented here use the double data type, which can
represent approximately 15 decimal digits.
Since not all fractional values can be expressed exactly, you might get unexpected results
because the display value does not match the stored value.
For example, the number 2.25 might be stored internally as 2.2499999..., which would round
down with arithmetic rounding, instead of up as you might expect. Also, the more calculations a
number is put through, the greater possibility that the stored binary value will deviate from the
ideal decimal value.
If this is the case, you may want to choose a different data type, such as Currency, which is exact
https://support.microsoft.com/enus/kb/196652

10/14

6/25/2015

HowToImplementCustomRoundingProcedures

to 4 decimal places.
You might also consider making the data types Variant and use CDec to convert everything to
the Decimal data type, which can be exact to 28 decimal digits.

Rounding Currency Values


When you use the Currency data type, which is exact to 4 decimal digits, you typically want to
round to 2 decimal digits for cents.
The Round2CB function below is a hardcoded variation that performs banker's rounding to 2
decimal digits, but does not multiply the original number. This avoids a possible overflow
condition if the monetary amount is approaching the limits of the Currency data type.

FunctionRound2CB(ByValXAsCurrency)AsCurrency
Round2CB=CCur(X/100)*100
EndFunction

Rounding Decimal Values


The following is an example of asymmetric arithmetic rounding using the Decimal data type:

FunctionAsymArithDec(ByValXAsVariant,_
OptionalByValFactorAsVariant=1)AsVariant
IfNotIsNumeric(X)Then
AsymArithDec=X
Else
IfNotIsNumeric(Factor)ThenFactor=1
AsymArithDec=Int(CDec(X*Factor)+.5)
EndIf
EndFunction

https://support.microsoft.com/enus/kb/196652

11/14

6/25/2015

HowToImplementCustomRoundingProcedures

Dropping Precision as a Shortcut in Rounding


As taught in school, rounding is usually arithmetic rounding using positive numbers. With this
type of rounding, you only need to know the number to 1 digit past where you are rounding to.
You ignore digits past the first decimal place. In other words, precision is dropped as a shortcut
to rounding the value.
For example, both 2.5 and 2.51 round up to 3, while both 2.4 and 2.49 round down to 2.
When you use banker's rounding or other methods that round .5 either up or down or when
you round negative numbers using asymmetric arithmetic rounding, dropping precision can lead
to incorrect results where you might not round to the nearest number.
For example, with banker's rounding, 2.5 rounds down to 2 and 2.51 rounds up to 3.
With asymmetric arithmetic rounding, 2.5 rounds up to 2 while 2.51 rounds down to 3.
The userdefined functions presented in this article take the number's full precision into account
when performing rounding.

REFERENCES
Visual Basic Help, version 6.0; topic: Int, Fix Functions; Round Function
Microsoft Transact SQL Help; topic: Round Function; Floor Function; Ceiling Function
c Microsoft Corporation 1998, All Rights Reserved. Contributions by Malcolm Stewart, Microsoft
Corporation.

Properties
Article ID: 196652 Last Review: 07/15/2004 15:02:00 Revision: 3.2
Applies to

https://support.microsoft.com/enus/kb/196652

12/14

6/25/2015

HowToImplementCustomRoundingProcedures

Microsoft Visual Basic 5.0 Control Creation Edition


Microsoft Visual Basic 5.0 Learning Edition
Microsoft Visual Basic 6.0 Learning Edition
Microsoft Visual Basic 5.0 Professional Edition
Microsoft Visual Basic 6.0 Professional Edition
Microsoft Visual Basic 5.0 Enterprise Edition
Microsoft Visual Basic 6.0 Enterprise Edition
Microsoft Visual Basic for Applications 5.0
Microsoft Visual Basic for Applications 6.0
Microsoft SQL Server 6.0 Standard Edition
Microsoft SQL Server 6.5 Standard Edition
Microsoft SQL Server 7.0 Standard Edition
Keywords:
kbhowto KB196652

Support
Account support
Supported products list
Product support lifecycle

Security

https://support.microsoft.com/enus/kb/196652

13/14

6/25/2015

HowToImplementCustomRoundingProcedures

Virus and security


Safety & Security Center
Download Security Essentials
Malicious Software Removal Tool

Contact Us
Report a support scam
Report abuse
Disability Answer Desk
Locate Microsoft addresses worldwide

English(UnitedStates)

Termsofuse Privacy&cookies

https://support.microsoft.com/enus/kb/196652

Trademarks

2015Microsoft

14/14

S-ar putea să vă placă și