如何实现自定义舍入过程

文章翻译 文章翻译
文章编号: 196652 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

有许多不同的舍入算法的 Microsoft 产品中可用。为应用程序的舍入算法范围是从舍入运算在 Excel 的工作表 Round() 函数到 Visual Basic 中 CInt()、 CLng() 和 Round() 函数中的银行家舍入。本文介绍了什么在各种 Visual Basic 的舍入的功能并提供了一些示例使用该函数的应用程序。此外,文章包括实现各种舍入算法的示例函数。

更多信息

舍入疑难解答

您需要舍入时您希望将更高的精度的数字转换为多个较低的精度。最常见的情况是当您需要将一个浮点数转换为整数。

向下舍入

最简单的化整形式为截断。所需的精度后的任何数字都只需将被忽略。VBA Fix() 函数是截断的示例。例如对于 Fix(3.5) 3,并且 Fix(-3.5)-3。

Int() 函数舍入为最高整数小于值。 Int() 和 Fix() 与正数截断的-作用相同的方式,但是负数给出不同的结果: Int(-3.5) 提供-4。

Fix() 函数是一种对称四舍五入,因为它会以相同的方式影响量 (绝对值) 的正和负号。Int() 函数是一个示例的非对称四舍五入,因为它会影响正和负号的方式不同。

Excel 有类似电子表格函数: Int()、 Floor() 和 RoundDown()。 Int() 同样适用,如同 Int() Visual Basic 中为应用程序。 Floor() 截断正数的值,但使用负数时无法正常工作。 RoundDown() 函数工作 VBA Fix() 函数相同的方式。

Microsoft SQL Server 都有一个可以像在 VBA Fix() 函数的 Round() 函数。SQL Server 也有同样为 VBA Int() 函数适用的 Floor() 函数。

向上舍入

SQL Server 和 Excel 都有一个函数称为 Ceiling(),始终舍入为下一个值的小部分值向上 (更多正值)。

Visual Basic 应用程序不具有相应的往返向上函数。但是,对于负值的数字 Fix() 和 Int() 可用于在不同的方法中的向上,舍入。

Fix() 将舍入到 0 (向上绝对意义上说但向下的绝对大小)。Fix(-3.5) 是-3.5。

Int() 将舍入远离 0 (向上的绝对大小但向下绝对意义上)。Int(-3.5) 是-4。

算术舍入

时始终舍入向下或向上,结果数字不一定是在与最接近原始的编号。例如对于舍入到 1 1.9,如果不同之处是比如果您其舍入到 2 很大。可以很容易地查看到 2.4 1.6 的数字应被舍入到 2。

但是,为什么这是介于 1 和 2 之间等距 1.5 版?按照约定,半方式数是向上舍入的。

您可以实现对称方式半方式数字进行舍入,这样-.5 会向下舍入为-1,或位置-.5 向上舍入到 0 的非对称方式。

下面的函数提供对称的算术舍入:
Excel Round() 电子表格函数。
SQL Server Round() 函数可以执行对称算法舍入。

下面的函数提供了不对称算法舍入:
Round() Java 数学库的方法。

Visual Basic 应用程序不具有执行算术舍入的任何函数。

成双

当您添加圆角的值一起,始终舍入.5 在同一个方向导致增长的更多的数字的偏差加在一起。最大限度地减少偏量的一种方法是使用成双。

banker 的舍入将舍入.5 有时向上和向下有时。该约定是舍入到接近的偶数,以便 1.5 版和 2.5 舍入到 2,和 3.5 以及 4.5 两者舍入到 4。成双是对称的。

在 Visual Basic 中为应用程序,以下数字函数执行成双: CByte()、 CInt()、 CLng()、 CCur() 和 Round()。

没有执行成双的 Excel 电子表格函数。

随机舍入

甚至成双可以偏移总计。您可以采取一些额外步骤通过舍入真正随机的方式.向上或向下 5 移除偏量。此的方式即使数据故意偏离,偏量可能会最小化。但是,使用随机舍入的随机分布数据可能会导致比成双的较大偏量。随机舍入可能会导致对相同的数据的两个不同的总计。

没有 Microsoft 产品实现任何种类的随机舍入过程。

备用舍入

备用舍入将四舍五入最多.5.5 下之间上连续调用。

没有 Microsoft 产品实现一个备用的舍入过程。

Round() 函数是下面的不一致现象: 实现

由于历史原因 Round() 函数未实现以在不同的 Microsoft 产品之间一致的方式。

下表与实现相关产品:
   Product                             Implementation
   ----------------------------------------------------------------------
   Visual Basic for Applications 6.0   Banker's Rounding
   Excel Worksheet                     Symmetric Arithmetic Rounding
   SQL Server                          Either Symmetric Arithmetic Rounding
                                       or Symmetric Round Down (Fix)
                                       depending on arguments

   Java Math library                   Asymmetric Arithmetic Rounding
				

在 Visual Basic 6.0 和 Visual Basic 6.0 应用程序的 Round() 函数执行成双。它有一个可选的第二个参数,指定的小数位数舍入到数:
   Debug.Print Round(2.45, 1) returns 2.4.
				

示例数据

下表显示一些示例数据和舍入的各种方法的效果在数字和生成的总计。
   Number/Int./Fix/Ceiling/Asym. Arith./Sym. Arith./Banker's/Random/Alt.
   ---------------------------------------------------------------------
   -2.6   -3   -2  -2      -3          -3           -3       -3     -3
   -2.5   -3   -2  -2      -2          -3           -2       -2     -3
   -2.4   -3   -2  -2      -2          -2           -2       -2     -2
   -1.6   -2   -1  -1      -2          -2           -2       -2     -2
   -1.5   -2   -1  -1      -1          -2           -2       -1     -1
   -1.4   -2   -1  -1      -1          -1           -1       -1     -1
   -0.6   -1    0   0      -1          -1           -1       -1     -1
   -0.5   -1    0   0       0          -1            0       -1     -1
   -0.4   -1    0   0       0           0            0        0      0
    0.4    0    0   1       0           0            0        0      0
    0.5    0    0   1       1           1            0        1      1
    0.6    0    0   1       1           1            1        1      1
    1.4    1    1   2       1           1            1        1      1
    1.5    1    1   2       2           2            2        1      1
    1.6    1    1   2       2           2            2        2      2
    2.4    2    2   3       2           2            2        2      2
    2.5    2    2   3       3           3            2        3      3
    2.6    2    2   3       3           3            3        3      3
				

所有数字的总和:
   Number/Int./Fix/Ceiling/Asym. Arith./Sym. Arith./Banker's/Random/Alt.
   ---------------------------------------------------------------------
   0.0    -9   0   9       3            0           0        1      0
				

所有负数值的总和:
   Number/Int./Fix/Ceiling/Asym. Arith./Sym. Arith./Banker's/Random/Alt.
   ---------------------------------------------------------------------
   -13.5  -18  -9  -9      -12          -15         -13      -13    -14
				

所有的正数的总数:
   Number/Int./Fix/Ceiling/Asym. Arith./Sym. Arith./Banker's/Random/Alt.
   ---------------------------------------------------------------------
   13.5   9    9   18      15           15          13       14     14
				

下表显示了各种舍入方法之间的时差。随机分布的正和负号、 Fix()、 对称的算术舍入、 成双,和交替舍入提供实际的合计之间最少的差别不远后面随机舍入。

但是,如果数字是要么所有正的或所有负 banker 的舍入,交替舍入,并随机舍入提供最少的实际总计区别。

用户定义的舍入函数的示例

在下面的函数列表部分中的代码示例提供示例实现的每个舍入的类型所述。

提供该功能是:
   AsymDown      Asymmetrically rounds numbers down - similar to Int().
                 Negative numbers get more negative.

   SymDown       Symmetrically rounds numbers down - similar to Fix().
                 Truncates all numbers toward 0.
                 Same as AsymDown for positive numbers.

   AsymUp        Asymmetrically rounds numbers fractions up.
                 Same as SymDown for negative numbers.
                 Similar to Ceiling.

   SymUp         Symmetrically rounds fractions up - that is, away from 0.
                 Same as AsymUp for positive numbers.
                 Same as AsymDown for negative numbers.

   AsymArith     Asymmetric arithmetic rounding - rounds .5 up always.
                 Similar to Java worksheet Round function.

   SymArith      Symmetric arithmetic rounding - rounds .5 away from 0.
                 Same as AsymArith for positive numbers.
                 Similar to Excel Worksheet Round function.

   BRound        Banker's rounding.
                 Rounds .5 up or down to achieve an even number.
                 Symmetrical by definition.

   RandRound     Random rounding.
                 Rounds .5 up or down in a random fashion.

   AltRound      Alternating rounding.
                 Alternates between rounding .5 up or down.

   ATruncDigits  Same as AsyncTrunc but takes different arguments.
				

所有这些函数带两个参数: 要舍入数和一个可选的因素。如果省略系数,然后在函数将返回一个整数,通过上述方法之一创建。如果指定该因子,则由创建不同的舍入效果因子缩放数。 例如 AsymArith (2.55,10) 将产生 2.6,也就是它舍入到 1/因子 = 1/10 = 0.1。

注: A 系数为 0 会产生运行时错误: 1/因子 = 1/0。

下表显示了各种因素的影响:
   Expression       Result  Comment
   --------------------------------------------------------------------
   AsymArith(2.5)     3     Rounds up to next integer.
   BRound(2.18, 20)   2.2   Rounds to the nearest 5 cents (1/20 dollar).
   SymDown(25, .1)   20     Rounds down to an even multiple of 10.
				

上面说明例外情况是 ADownDigits,这是一个模板函数,允许您指定的小数位数,而不是一个因素。
   Expression            Result Comment
   ---------------------------------------------------------------------
   ADownDigits(2.18, 1)    2.1  Rounds down to next multiple of 10 ^ -1.
				

函数列表


   Function AsymDown(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
     AsymDown = Int(X * Factor) / Factor
   End Function

   Function SymDown(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
     SymDown = Fix(X * Factor) / Factor
   '  Alternately:
   '  SymDown = AsymDown(Abs(X), Factor) * Sgn(X)
   End Function

   Function AsymUp(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
   Dim Temp As Double
     Temp = Int(X * Factor)
     AsymUp = (Temp + IIf(X = Temp, 0, 1)) / Factor
   End Function

   Function SymUp(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
   Dim Temp As Double
     Temp = Fix(X * Factor)
     SymUp = (Temp + IIf(X = Temp, 0, Sgn(X))) / Factor
   End Function

   Function AsymArith(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
     AsymArith = Int(X * Factor + 0.5) / Factor
   End Function

   Function SymArith(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
     SymArith = Fix(X * Factor + 0.5 * Sgn(X)) / Factor
   '  Alternately:
   '  SymArith = Abs(AsymArith(X, Factor)) * Sgn(X)
   End Function

   Function BRound(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
   '  For smaller numbers:
   '  BRound = CLng(X * Factor) / Factor
   Dim Temp As Double, FixTemp As Double
     Temp = X * Factor
     FixTemp = Fix(Temp + 0.5 * Sgn(X))
     ' Handle rounding of .5 in a special manner
     If Temp - Int(Temp) = 0.5 Then
       If FixTemp / 2 <> Int(FixTemp / 2) Then ' Is Temp odd
         ' Reduce Magnitude by 1 to make even
         FixTemp = FixTemp - Sgn(X)
       End If
     End If
     BRound = FixTemp / Factor
   End Function

   Function RandRound(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
   ' Should Execute Randomize statement somewhere prior to calling.
   Dim Temp As Double, FixTemp As Double
     Temp = X * Factor
     FixTemp = Fix(Temp + 0.5 * Sgn(X))
     ' Handle rounding of .5 in a special manner.
     If Temp - Int(Temp) = 0.5 Then
       ' Reduce Magnitude by 1 in half the cases.
       FixTemp = FixTemp - Int(Rnd * 2) * Sgn(X)
     End If
     RandRound = FixTemp / Factor
   End Function

   Function AltRound(ByVal X As Double, _
            Optional ByVal Factor As Double = 1) As Double
   Static fReduce As Boolean
   Dim Temp As Double, FixTemp As Double
     Temp = X * Factor
     FixTemp = Fix(Temp + 0.5 * Sgn(X))
     ' Handle rounding of .5 in a special manner.
     If Temp - Int(Temp) = 0.5 Then
       ' Alternate between rounding .5 down (negative) and up (positive).
       If (fReduce And Sgn(X) = 1) Or (Not fReduce And Sgn(X) = -1) Then
       ' Or, replace the previous If statement with the following to
       ' alternate between rounding .5 to reduce magnitude and increase
       ' magnitude.
       ' If fReduce Then
         FixTemp = FixTemp - Sgn(X)
       End If
       fReduce = Not fReduce
     End If
     AltRound = FixTemp / Factor
   End Function

   Function ADownDigits(ByVal X As Double, _
            Optional ByVal Digits As Integer = 0) As Double
     ADownDigits = AsymDown(X, 10 ^ Digits)
   End Function
				

注: 随 Excel 的 MRound() 工作表函数,内置的除外-中的舍入函数需要参数的 ADownDigits,其中第二个参数指定的位数,而不是一个因素的方式。

舍入此处提供的实现使用 MRound(),类似的一个因素,这是更灵活,因为您不必非要舍入到 10 的幂。 您可以编写包装函数 ADownDigits 的方式。

浮动点限制

此处提供的舍入实现的所有使用双数据类型,可以表示大约 15 的十进制数字。

因为可以完全表示不是所有的小数值,您可能会产生意外的结果,因为显示值与存储的值不匹配。

例如对于数 2.25 可能存储在内部作为 2.2499999...,从而将下舍入与算术舍入,而不是最多正如您可能希望的那样。此外,多个计算的数字将放入通过更大存储的二进制值将偏离理想的十进制值的可能性。

这是否大小写您可能希望选择一个不同的数据类型,such as 货币,这是精确到 4 decimal places。

您还可能需要考虑的使变量的数据类型和使用 CDec() 若要将所有内容转换为十进制数据类型,可精确到 28 的十进制数字。

舍入的货币值

当您使用货币数据类型,这是精确到 4 的十进制位数,您通常要舍入到 2 个小数位数为美分。

下面 Round2CB 函数是执行成双为 2 的十进制位数,但不会将原始编号不相乘的硬编码变体。货币金额接近的货币数据类型限制时,这样可以避免可能的溢出。
   Function Round2CB (ByVal X As Currency) As Currency
     Round2CB = CCur(X / 100) * 100
   End Function
				

Decimal 值舍入

下面是一个不对称算法四舍五入使用十进制数据类型的示例:
   Function AsymArithDec(ByVal X As Variant, _
            Optional ByVal Factor As Variant = 1) As Variant
     If Not IsNumeric(X) Then
       AsymArithDec = X
     Else
       If Not IsNumeric(Factor) Then Factor = 1
       AsymArithDec = Int(CDec(X * Factor) + .5)
     End If
   End Function
				

正在删除精度为舍入中的快捷方式

如在学校讲授,舍入是通常算术舍入使用正数。使用这种类型的舍入,您只需要了解过去 1 位,四舍五入为数。过去的第一个小数位数,则忽略。也就精度被删除作为一种快捷方式到值的舍入。

例如对于 2.5 和 2.51 圆形最多 3,而 2.4 和 2.49 下舍入到 2。

当您使用成双 (或其他方法的向上或向下舍入.5) 或舍入使用不对称算法舍入的负数,删除精度可能会导致不正确的结果,您可能不四舍五入为最接近的数字。

例如对于与成双,2.5 舍 2 2.51 舍入到最多 3。

带有非对称算法圆-2.5 舍入达-2,而-2.51 舍入到-3。

这篇文章中介绍了用户定义的函数数目的完全精度时考虑执行舍入。

参考

帮助的 Visual Basic 6.0 版 ; 主题: Int,修复函数 ; 圆形的函数

Microsoft 进行交易 SQL 帮助 ; 主题: 圆形函数 ; Floor 函数 ; 天花板函数

(c) Microsoft Corporation 1998,保留的所有权限。通过贡献 Malcolm Stewart,Microsoft 公司。

属性

文章编号: 196652 - 最后修改: 2004年7月15日 - 修订: 3.2
这篇文章中的信息适用于:
  • Microsoft Visual Basic Control Creation Edition
  • Microsoft Visual Basic 5.0 学习版
  • Microsoft Visual Basic 6.0 学习版
  • Microsoft Visual Basic 5.0 专业版
  • Microsoft Visual Basic 6.0 专业版
  • Microsoft Visual Basic 5.0 企业版
  • Microsoft Visual Basic Enterprise Edition for Windows 6.0
  • Microsoft Visual Basic for Applications 5.0
  • Microsoft Visual Basic for Applications 6.0
  • Microsoft SQL Server 6.0 标准版
  • Microsoft SQL Server 6.5 标准版
  • Microsoft SQL Server 7.0 标准版
关键字:?
kbmt kbhowto KB196652 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 196652
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com