如何确定vba中数字的准确性?一个数字有多少个小数位?

时间:2014-06-12 14:55:17

标签: excel vba

我需要一种方法来判断数字的准确程度。例如,如果我有x = 3.14,我需要编写代码,可以告诉3.14准确到1个单位。或者,如果我有x = 31300,我需要知道x只有几百个才准确吗?

编辑:也许准确是一个糟糕的选择。我正在使用Bisection算法来找到我适合某些x,y坐标的多项式的根。我需要提供一定程度的准确度(DOA),告诉算法何时足够接近实际的根停止。因此,如果数据为12.1,我希望我的DOA为+/- 0.01。

3 个答案:

答案 0 :(得分:0)

数字在计算中有各种表示,非整数用浮点或固定点表示。

不幸的是,VBA中没有本机定点类型。

对于Single和Double,VBA使用IEEE 754-1985,它使用基数2指数作为其内部表示。因此,0.01例如不能具有精确值(但VBA会将其隐藏)

Debug.Print 0.1 * 0.1 = 0.01 ' Prints False

还有另一种名为Decimal的类型,其基数为10指数 很遗憾,您无法声明Decimal类型的变量,因此您需要使用Variant CDec可用于将String,Integer,Double等转换为Decimal

Debug.Print CDec(0.1) * CDec(0.1) = CDec(0.01) ' Prints True

我们知道,对于Decimal,精度在小数点后最多为28位。要确定第一个非零数字的位置,我们只需要将数字除以10直到四舍五入为止

Function ndec(n As Variant) As Variant
    Dim n1 As Variant
    Dim n2 As Variant
    Dim i As Long

    n1 = CDec(n)
    n2 = n1

    If n1 = 0 Then
        ndec = CDec(0)
        Exit Function
    End If

    Do
        n1 = CDec(n1 / 10)
        i = i + 1
    Loop While CDec((n1 * 10 ^ (i Mod 28)) * 10 ^ (i - i Mod 28)) = n2 ' it should be CDec(n1 * 10 ^ i) = n2 but 10^i overflows when i > 28 so we split the operation

    ndec = CDec(10 ^ (i - 29))
End Function

用法:

ndec(1.34) ' returns 0.01
ndec(12340) ' returns 10

附加信息

你需要非常小心,但浮点数的精度可以是2个数字可以有相同的表示形式:

Sub test()
    Dim i1 As Long, i2 As Long: i1 = 16777221: i2 = 16777220
    Dim f1 As Single, f2 As Single: f1 = 16777221: f2 = 16777220
    Dim d1 As Double, d2 As Double: d1 = 16777221: d2 = 16777220

    Debug.Print "Integer soustraction : " & i1 - i2 ' printf 1
    Debug.Print "Single soustraction : " & f1 - f2 ' printf 0
    Debug.Print "Double soustraction : " & d1 - d2 ' printf 1
End Sub

更多信息: What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:0)

一个更简单的解决方案是使用WorksheetFunction.Round(arg1,arg2)。
arg1是要评估的数字;

arg2是舍入精度;小数点右边为正,小数点左边为负。

让您的算法评估arg1(未舍入)并返回新结果arg3(未舍入)。然后使用所需的精度(arg2)将舍入的算法结果(arg3)与舍入后的原始结果(arg1)

您需要进行比较的代码行是

If WorksheetFunction.Round(arg1, arg2) = WorksheetFunction.Round(arg3, arg2) Then 
'your next steps here

通过下面的代码可以看到Round函数的效果,下面的代码传递arg1,将其递增到arg3,然后比较舍入后的arg1和arg3值

Public Sub test()

Dim arg1 As Double
Dim arg3 As Double
Dim arg2rounded
Dim arg3rounded

arg1 = 1652.23564
Do While 1 = 1
    arg3 = AlgResult(arg1) 'send a value to your algorithm routine
    Debug.Print "arg1 not rounded = " & arg1 & "  arg3 not rounded = " & arg3
    For arg2 = -4 To 4 'loop through presicion to see effect
        arg1rounded = WorksheetFunction.Round(arg1, arg2)
        arg3rounded = WorksheetFunction.Round(arg3, arg2)
        If arg1rounded = arg3rounded  Then
            Debug.Print arg1rounded & " = " & arg3rounded & " at desired precision of " & arg2
            Else: Debug.Print arg1rounded & " <> " & arg3rounded & " at desired precision of " & arg2
        End If
    Next
    arg1 = arg3
Loop
End Sub

Public Function AlgResult(EvalNum As Double) As Double

    AlgResult = EvalNum + 0.5

End Function

答案 2 :(得分:0)

B = A / (Left(A, InStr(1, A, ",") - 1) & Mid(A, InStr(1, A, ",") + 1, 30))
or
B = A / Replace(A, ",", "")