我需要一种方法来判断数字的准确程度。例如,如果我有x = 3.14,我需要编写代码,可以告诉3.14准确到1个单位。或者,如果我有x = 31300,我需要知道x只有几百个才准确吗?
编辑:也许准确是一个糟糕的选择。我正在使用Bisection算法来找到我适合某些x,y坐标的多项式的根。我需要提供一定程度的准确度(DOA),告诉算法何时足够接近实际的根停止。因此,如果数据为12.1,我希望我的DOA为+/- 0.01。
答案 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, ",", "")