java小数向上四舍五入_将值向上,向下,四舍五入或四舍五入

java小数向上四舍五入

四舍五入应该就在眼前 (Rounding should be right at hand)

In many areas, rounding that accurately follows specific rules are needed - accounting, statistics, insurance, etc.

在许多领域,都需要精确遵循特定规则的舍入-会计,统计,保险等。

Unfortunately, the native functions of VBA that can perform rounding are either missing, limited, inaccurate, or buggy, and all address only a single rounding method. The upside is that they are fast, and that may in some situations be important.

不幸的是,可以执行舍入的VBA的本机功能要么丢失,有限,不准确或有错误,而且全部仅解决一种舍入方法。 这样做的好处是速度快,在某些情况下可能很重要。

However, often precision is mandatory, and with the speed of computers today, a little slower processing will hardly be noticed, indeed not for processing of single values. All the functions presented here run at about 1 µs.

但是,精度通常是强制性的,并且随着当今计算机的发展,几乎不会注意到处理速度稍慢一些,的确不是单个值的处理。 此处介绍的所有功能的运行时间约为1 µs。

They cover the normal rounding methods:

它们涵盖了正常的舍入方法:

  • Round down, with the option to round negative values towards zero

    向下舍入,可以将负值舍入为零
  • Round up, with the option to round negative values away from zero

    向上舍入,可以将负值舍入为零
  • Round by 4/5, either away from zero or to even  (Banker's Rounding)

    四舍五入, 从零 (银行家取整)
  • Round to a count of significant figures

    四舍五入计算重要数字

The first three functions accept all the numeric data types, while the last exists in three varieties - for Currency, Decimal, and Double respectively.

前三个函数接受所有数值数据类型,而后三个函数以三种形式存在-分别用于Currency,Decimal和Double。

They all accept a specified count of decimals - including a negative count which will round to tens, hundreds, etc. Those with Variant as return type will return Null for incomprehensible input.

它们都接受指定的小数位数-包括将舍入为数十,数百等的负数。将Variant作为返回类型的那些将返回Null,以获取难以理解的输入。

背景 (Background)

More than ten years ago, Donald Lessau created a site dealing with Visual Basic issues: VBspeed. One of these issues was to create a replacement for Round  which was (and still is) buggy, though fast. Also, it could (and still can) only perform Banker's Rounding which may not be what you expect when you look for 4/5 rounding. Several suggestions were put forward, one extremely simple using Format; but string handling, as it is, is not very fast, so other solutions were thought out, all more or less wrapped around Int(Value + 0.5). They can all be found here.

十多年前, Donald Lessau创建了一个处理Visual Basic问题的站点: VBspeed 。 这些问题之一是创建Round的替代品,该替代品曾经(现在仍然)是越野车,尽管速度很快。 另外,它可能(仍然可以)仅执行银行家四舍五入,这在您寻求4/5四舍五入时可能并非您所期望的。 提出了一些建议,一种非常简单的使用Format格式。 但是,由于字符串处理的速度不是很快,因此考虑了其他解决方案,这些解决方案或多或少都围绕Int(Value + 0.5)。 他们都可以在这里找到。

If you are convinced that Round is not buggy, just try this simple example:

如果您确信Round不是越野车,请尝试以下简单示例:

RoundedValue = Round(32.675, 2) 

It will return 32.67 while both a normal 4/5 rounding as well as Banker's Rounding would return 32.68.

它将返回32.67,而正常的4/5取整和Banker的取整将返回32.68。

Today, computers are much faster, and while Round is very fast, it will in many cases be preferable with a function that is a bit slower if it on the other hand always returns the expected result. 

如今,计算机的速度要快得多,而Round的速度非常快,但在很多情况下,如果它总是返回预期的结果,则它的功能会有些慢,因此它是更可取的。

So - from these old contributions - I've brushed up the old 4/5 rounding function with an option for choosing Banker's Rounding, and added sibling functions for rounding up or down (also with options) with focus on the ability to correctly handle as wide a range of input values as possible. Still, they run at about 1 µs. Finally, for completeness and because it is quite different from the other functions, a function for rounding to significant figures was added.

所以-从这些旧的贡献中-我用选择Banker's Rounding的选项刷了旧的4/5舍入函数,并添加了用于向上或向下舍入的同级函数(还带有选项),着重于正确处理尽可能宽的输入值范围。 尽管如此,它们仍以约1 µs的速度运行。 最后,出于完整性的考虑,并且由于它与其他功能完全不同,因此添加了一个四舍五入为有效数字的功能。

It's important to stress, that there is no right  or wrong  rounding method, thus it makes no sense to argue why Mid Rounding away from zero  is "better" than Banker's Rounding. What's important, however, is to know how each method operates, so you can choose the optimum method for the current task.

需要强调的是,没有正确错误的舍入方法,因此没有理由争辩说为什么中间舍入距零比“ 银行家”舍入 “更好”。 但是,重要的是要知道每种方法的工作方式,因此您可以为当前任务选择最佳方法。

例子 (Examples)

It can be useful to list examples that shows the differences between the different rounding methods and how they act upon positive as well as negative values. Here are just a few:

列出显示不同取整方法之间的差异以及它们如何作用于正值和负值的示例可能会很有用。 这里仅仅是少数:

rounding method

value n



12.34412.34512.34612.35412.35512.356
RoundUp(n, 2, False)12.3512.3512.3512.3612.3612.36
RoundUp(n, 2, True)12.3512.3512.3512.3612.3612.36
RoundDown(n, 2, False)12.3412.3412.3412.3512.3512.35
RoundDown(n, 2, True)12.3412.3412.3412.3512.3512.35
RoundMid(n, 2, False)12.3412.3512.3512.3512.3612.36
RoundMid(n, 2, True)12.3412.3412.3512.3512.3612.36
RoundSignificantDec(n, 4, , False)12.3412.3512.3512.3512.3612.36
RoundSignificantDec(n, 4, , True)12.3412.3412.3512.3512.3612.36

-12.344-12.345-12.346-12.354-12.355-12.356
RoundUp(n, 2, False)-12.34-12.34-12.34-12.35-12.35-12.35
RoundUp(n, 2, True)-12.35-12.35-12.35-12.36-12.36-12.36
RoundDown(n, 2, False)-12.35-12.35-12.35-12.36-12.36-12.36
RoundDown(n, 2, True)-12.34-12.34-12.34-12.35-12.35-12.35
RoundMid(n, 2, False)-12.34-12.35-12.35-12.35-12.36-12.36
RoundMid(n, 2, True)-12.34-12.34-12.35-12.35-12.36-12.36
RoundSignificantDec(n, 4, , False)-12.34-12.35-12.35-12.35-12.36-12.36
RoundSignificantDec(n, 4, , True)-12.34-12.34-12.35-12.35-12.36-12.36
舍入法

值n



12.344 12.345 12.346 12.354 12.355 12.356
取整(n,2,False) 12.35 12.35 12.35 12.36 12.36 12.36
舍入(n,2,True) 12.35 12.35 12.35 12.36 12.36 12.36
RoundDown(n,2,False) 12.34 12.34 12.34 12.35 12.35 12.35
RoundDown(n,2,True) 12.34 12.34 12.34 12.35 12.35 12.35
RoundMid(n,2,False) 12.34 12.35 12.35 12.35 12.36 12.36
RoundMid(n,2,True) 12.34 12.34 12.35 12.35 12.36 12.36
RoundSignificantDec(n,4,,False) 12.34 12.35 12.35 12.35 12.36 12.36
RoundSignificantDec(n,4,,True) 12.34 12.34 12.35 12.35 12.36 12.36

-12.344 -12.345 -12.346 -12.354 -12.355 -12.356
取整(n,2,False) -12.34 -12.34 -12.34 -12.35 -12.35 -12.35
舍入(n,2,True) -12.35 -12.35 -12.35 -12.36 -12.36 -12.36
RoundDown(n,2,False) -12.35 -12.35 -12.35 -12.36 -12.36 -12.36
RoundDown(n,2,True) -12.34 -12.34 -12.34 -12.35 -12.35 -12.35
RoundMid(n,2,False) -12.34 -12.35 -12.35 -12.35 -12.36 -12.36
RoundMid(n,2,True) -12.34 -12.34 -12.35 -12.35 -12.36 -12.36
RoundSignificantDec(n,4,,False) -12.34 -12.35 -12.35 -12.35 -12.36 -12.36
RoundSignificantDec(n,4,,True) -12.34 -12.34 -12.35 -12.35 -12.36 -12.36

More examples can be found in the two modules in the code with suffix Test.

在带有后缀Test的代码的两个模块中可以找到更多示例。

功能 (The functions)

The main function - rounding by 4/5 - goes like this. Please note the in-line comments for details:

主要功能-四舍五入-这样。 请注意在线注释以获取详细信息:

' Common constants. 
' 
' Base values. 
Public Const Base2      As Double = 2 
Public Const Base10     As Double = 10 


' Rounds Value by 4/5 with count of decimals as specified with parameter NumDigitsAfterDecimal. 
' 
' Rounds to integer if NumDigitsAfterDecimal is zero. 
' 
' Rounds correctly Value until max/min value limited by a Scaling of 10 
' raised to the power of (the number of decimals). 
' 
' Uses CDec() to prevent bit errors of reals. 
' 
' Execution time is about 1µs. 
' 
' 2018-02-09. Gustav Brock, Cactus Data ApS, CPH. 
' 
Public Function RoundMid( _ 
    ByVal Value As Variant, _ 
    Optional ByVal NumDigitsAfterDecimal As Long, _ 
    Optional ByVal MidwayRoundingToEven As Boolean) _ 
    As Variant 
 
    Dim Scaling     As Variant 
    Dim Half        As Variant 
    Dim ScaledValue As Variant 
    Dim ReturnValue As Variant 
     
    ' Only round if Value is numeric and ReturnValue can be different from zero. 
    If Not IsNumeric(Value) Then 
        ' Nothing to do. 
        ReturnValue = Null 
    ElseIf Value = 0 Then 
        ' Nothing to round. 
        ' Return Value as is. 
        ReturnValue = Value 
    Else 
        Scaling = CDec(Base10 ^ NumDigitsAfterDecimal) 
         
        If Scaling = 0 Then 
            ' A very large value for NumDigitsAfterDecimal has minimized scaling. 
            ' Return Value as is. 
            ReturnValue = Value 
        ElseIf MidwayRoundingToEven Then 
            ' Banker's rounding. 
            If Scaling = 1 Then 
                ReturnValue = Round(Value) 
            Else 
                ' First try with conversion to Decimal to avoid bit errors for some reals like 32.675. 
                ' Very large values for NumDigitsAfterDecimal can cause an out-of-range error when dividing. 
                On Error Resume Next 
                ScaledValue = Round(CDec(Value) * Scaling) 
                ReturnValue = ScaledValue / Scaling 
                If Err.Number <> 0 Then 
                    ' Decimal overflow. 
                    ' Round Value without conversion to Decimal. 
                    ReturnValue = Round(Value * Scaling) / Scaling 
                End If 
            End If 
        Else 
            ' Standard 4/5 rounding. 
            ' Very large values for NumDigitsAfterDecimal can cause an out-of-range error when dividing. 
            On Error Resume Next 
            Half = CDec(0.5) 
            If Value > 0 Then 
                ScaledValue = Int(CDec(Value) * Scaling + Half) 
            Else 
                ScaledValue = -Int(-CDec(Value) * Scaling + Half) 
            End If 
            ReturnValue = ScaledValue / Scaling 
            If Err.Number <> 0 Then 
                ' Decimal overflow. 
                ' Round Value without conversion to Decimal. 
                Half = CDbl(0.5) 
                If Value > 0 Then 
                    ScaledValue = Int(Value * Scaling + Half) 
                Else 
                    ScaledValue = -Int(-Value * Scaling + Half) 
                End If 
                ReturnValue = ScaledValue / Scaling 
            End If 
        End If 
        If Err.Number <> 0 Then 
            ' Rounding failed because values are near one of the boundaries of type Double. 
            ' Return value as is. 
            ReturnValue = Value 
        End If 
    End If 
     
    RoundMid = ReturnValue 
 
End Function 

Using it requires nothing more than importing (or copy/paste) the module RoundingMethods  included in the zip into your project. Then the functions can be used in a similar way that you would use Round:

使用它只需要将zip中包含的模块RoundingMethods导入(或复制/粘贴)到您的项目中。 然后,可以使用与Round相似的方式来使用函数:

RoundedValue = RoundMid(32.675, 2) 

However, it performs a normal 4/5 by default, and optionally Banker's Rounding.

但是,默认情况下,它会执行正常的4/5运算,也可以选择执行Banker的取整运算。

It is supplemented by the rounding up or down functions:

舍入或舍入功能对此功能进行了补充:

  • RoundUp

    围捕
  • RoundDown

    舍入

These act basically like -Int(-n)  or Int(n)  but also feature an option for rounding away  from zero or towards  zero respectively (see the example results above).

这些行为基本上像-Int(-n)INT(n)的 ,但还具有用于分别从零或舍去一个选项(见上面的例子中的结果)。

Rounding to significant figures is somewhat different, though scaling and rounding still is an essential part:

四舍五入到有效数字有些不同,尽管缩放和四舍五入仍然是必不可少的部分:

' Rounds Value to have significant figures as specified with parameter Digits. 
' 
' Performs no rounding if Digits is zero. 
' Rounds to integer if NoDecimals is True. 
' Digits can be any value between 1 and 14. 
' 
' Will accept values until about max/min Value of Double type. 
' At extreme values (beyond approx. E+/-300) with significant 
' figures of 10 and above, rounding is not 100% perfect due to 
' the limited precision of Double. 
' 
' For rounding of values within the range of type Decimal, use the 
' function RoundSignificantDec. 
' 
' Requires: 
'   Function Log10. 
' 
' 2018-02-09. Gustav Brock, Cactus Data ApS, CPH. 
' 
Public Function RoundSignificantDbl( _ 
    ByVal Value As Double, _ 
    ByVal Digits As Integer, _ 
    Optional ByVal NoDecimals As Boolean, _ 
    Optional ByVal MidwayRoundingToEven As Boolean) _ 
    As Double 
     
    Dim Exponent    As Double 
    Dim Scaling     As Double 
    Dim Half        As Variant 
    Dim ScaledValue As Variant 
    Dim ReturnValue As Double 
     
    ' Only round if result can be different from zero. 
    If (Value = 0 Or Digits <= 0) Then 
        ' Nothing to round. 
        ' Return Value as is. 
        ReturnValue = Value 
    Else 
        ' Calculate scaling factor. 
        Exponent = Int(Log10(Abs(Value))) + 1 - Digits 
        If NoDecimals = True Then 
            ' No decimals. 
            If Exponent < 0 Then 
                Exponent = 0 
            End If 
        End If 
        Scaling = Base10 ^ Exponent 
         
        If Scaling = 0 Then 
            ' A very large value for Digits has minimized scaling. 
            ' Return Value as is. 
            ReturnValue = Value 
        Else 
            ' Very large values for Digits can cause an out-of-range error when dividing. 
            On Error Resume Next 
            ScaledValue = CDec(Value / Scaling) 
            If Err.Number <> 0 Then 
                ' Return value as is. 
                ReturnValue = Value 
            Else 
                ' Perform rounding. 
                If MidwayRoundingToEven = False Then 
                    ' Round away from zero. 
                    Half = CDec(Sgn(Value) / 2) 
                    ReturnValue = CDbl(Fix(ScaledValue + Half)) * Scaling 
                Else 
                    ' Round to even. 
                    ReturnValue = CDbl(Round(ScaledValue)) * Scaling 
                End If 
                If Err.Number <> 0 Then 
                    ' Rounding failed because values are near one of the boundaries of type Double. 
                    ' Return value as is. 
                    ReturnValue = Value 
                End If 
            End If 
        End If 
    End If 
   
    RoundSignificantDbl = ReturnValue 
 
End Function 



' Returns Log 10 of Value. 
' 
' 2018-02-09. Gustav Brock, Cactus Data ApS, CPH. 
' 
Public Function Log10( _ 
    ByVal Value As Double) _ 
    As Double 
 
    ' No error handling as this should be handled 
    ' outside this function. 
    ' 
    ' Example: 
    ' 
    '     If MyValue > 0 then 
    '         LogMyValue = Log10(MyValue) 
    '     Else 
    '         ' Do something else ... 
    '     End If 
     
    Log10 = Log(Value) / Log(Base10) 
 
End Function 

For all functions, note that potential floating point errors are avoided by casting to Decimal with CDec.

对于所有函数,请注意,通过使用CDec强制转换为Decimal可以避免潜在的浮点错误。

更多的选择 (More options)

If you wish to study the peculiars of the native Round, then study the module RoundingMethodsTest  where a lot of values and results can be found. Also, should you wish to modify a function for your specific purpose, as a minimum it should pass the test included in the test module.

如果您想研究原生Round的特质,请研究RoundingMethodsTest模块,在其中可以找到很多值和结果。 另外,如果您希望针对特定目的修改功能,则至少应通过测试模块中包含的测试。

Also, a lot of variations is possible using the functions as a base.

同样,使用这些功能作为基础可以有很多变化。

For example, given the value n = 128.19:

例如,给定值n = 128.19:

Round to the nearest quarter (0.25):

四舍五入到最近的四分之一(0.25):

RoundedValued = RoundMid(n / 0.25) * 0.25
RoundedValued -> 128.25 

Round up to the nearest "bargain price"

四舍五入至最接近的“议价价格”

RoundedValue = RoundUp(n) - 0.01
RoundedValue -> 128.99 

Round to the nearest integer 5:

四舍五入到最接近的整数5:

RoundedValue = RoundMid(n / 5) * 5
RoundedValue = 130.00 

资料下载 (Downloads)

The current version can always be found at GitHub.

当前版本始终可以在GitHub上找到

The version 1.3.2 demo files for Office 365 is here: 

Office 365的1.3.2版演示文件位于此处:

Rounding 1.3.2.accdb

舍入1.3.2.accdb

Rounding 1.3.2.xlsm

取整1.3.2.xlsm

I hope you found this article useful. You are encouraged to ask questions, report any bugs or make any other comments about it below.

希望本文对您有所帮助。 鼓励您在下面提出问题,报告任何错误或对此作出任何其他评论。

Note: If you need further "Support" about this topic, please consider using the Ask a Question feature of Experts Exchange. I monitor questions asked and would be pleased to provide any additional support required in questions asked in this manner, along with other EE experts.

注意 :如果您需要有关此主题的更多“支持”,请考虑使用Experts Exchange 的“提问”功能。 我会监督提出的问题,并很高兴与其他电子工程师一起为以这种方式提出的问题提供所需的任何其他支持。

Please do not forget to press the "Thumbs Up" button if you think this article was helpful and valuable for EE members.

如果您认为本文对EE成员有用且有价值,请不要忘记按下“竖起大拇指”按钮。

翻译自: https://www.experts-exchange.com/articles/20299/Rounding-values-up-down-by-4-5-or-to-significant-figures.html

java小数向上四舍五入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值