我的数据库中有三个数字,想要在 if 语句中比较它们。
我有一个简单的 convert 函数,它仅返回 double 。
Public Function RetDbl(ByVal obj As Variant) As Double
On Error Resume Next
RetDbl = val(Replace(Nz(obj, 0), ",", "."))
End Function
声明是
If RetDbl(rs.value("NumA")) + RetDbl(rs.value("NumB")) <> (RetDbl(rs.value("NumC")) * 1000) Then
'[... do some code ...]
End If
使用 RetDbl(rs.value("NumA")) = 0.33
、RetDbl(rs.value("NumB") = 0.5
和 RetDbl( rs.value("NumC")) = 0.00083
这总是返回 false
我也尝试过:
在直接字段 (STRG + G) 中:?cdbl(0.33) + cdbl(0.50) = cdbl(0.83)
返回 false
。当我省略最后一部分时,它返回 0.83
如何比较这些数字?
最佳答案
比较 float 很困难。就在昨天,我发布了this question
我的解决方案:
Public Function DblSafeCompare(ByVal Value1 As Variant, ByVal Value2 As Variant) As Boolean
'Compares two variants, dates and floats are compared at high accuracy
Const AccuracyLevel As Double = 0.00000001
'We accept an error of 0.000001% of the value
Const AccuracyLevelSingle As Single = 0.0001
'We accept an error of 0.0001 on singles
If VarType(Value1) <> VarType(Value2) Then Exit Function
Select Case VarType(Value1)
Case vbSingle
DblSafeCompare = Abs(Value1 - Value2) <= (AccuracyLevelSingle * Abs(Value1))
Case vbDouble
DblSafeCompare = Abs(Value1 - Value2) <= (AccuracyLevel * Abs(Value1))
Case vbDate
DblSafeCompare = Abs(CDbl(Value1) - CDbl(Value2)) <= (AccuracyLevel * Abs(CDbl(Value1)))
Case vbNull
DblSafeCompare = True
Case Else
DblSafeCompare = Value1 = Value2
End Select
End Function
请注意,AccuracyLevel (epsilon) 可以设置为较小的值,并且我对单打和 double 使用相同的值,但它非常适合我的目的。
我使用的是相对 epsilon,但将其与第一个值相乘,而不是最大值,因为如果存在显着差异,则比较无论如何都会失败。
请注意,我正在使用 <=
而不是<
从那时起DblSafeCompare(cdbl(0) ,cdbl(0))
会失败
请注意,此函数检查类型相等性,因此将整数与长整型、 double 型与单精度型等进行比较都会失败。然而,比较 Null 与 Null 传递。
实现它:
?DblSafeCompare(cdbl(0.33) + cdbl(0.50) ,cdbl(0.83))
?DblSafeCompare(cdbl(0.331) + cdbl(0.50) ,cdbl(0.83))
关于vba - 比较 double 返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47814134/