比较双精度返回false

时间:2017-12-14 13:06:36

标签: vba ms-access

我的数据库中有三个数字,想要在if语句中对它们进行比较。

我有一个简单的conevert函数,只返回双精度。

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.33RetDbl(rs.value("NumB") = 0.5RetDbl(rs.value("NumC")) = 0.00083

这总是返回false

我也试过了:

在直接字段(STRG + G)中:?cdbl(0.33) + cdbl(0.50) = cdbl(0.83)返回false。当我遗漏最后一部分时,它会返回0.83

我如何比较这些数字?

2 个答案:

答案 0 :(得分:2)

比较浮动数字很难。就在昨天,我发布了this question

我的解决方案:

  <ul>
    <li><a routerLink="/about">About</a></li>
    <li><a routerLink="/knowledge">Knowledge</a></li>
    <li><a routerLink="/questions">Questions</a></li>
    <li><a routerLink="/passions">Passions</a></li>
  </ul>

请注意,AccuracyLevel(epsilon)可以设置为较小的值,并且我使用相同的单值和双精度值,但它对我的目的来说很好。

我使用相对epsilon,但是将它与第一个相加,而不是最大值,因为如果存在显着差异,则比较将无论如何都会失败。

请注意,我使用的是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 而不是<=,因为其他<会失败

请注意,此函数检查类型是否相等,因此将整数与long,double to singleles等进行比较都会失败。但是,比较Null到Null的传递。

实施它:

DblSafeCompare(cdbl(0) ,cdbl(0))

答案 1 :(得分:2)

比较浮点数确实是一个问题,如果你试图在不了解浮点数的性质的情况下进行。

以下是一篇很好的文章 - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlHow dangerous is it to compare floating point values?

一般来说,这个问题是如此之大,以至于像C#这样的某些语言开发了一个名为Decimal的特定类,这使得比较运行非同一个非程序员的预期。 Decimal info。在VBA中,类似的类是Currency。因此

CCur(0.33) + CCur(0.50) = CCur(0.83)

返回True。 VBA支持函数CDec,它将double转换为十进制数,但它不支持类Decimal。因此:

CDec(0.33) + CDec(0.50) = CDec(0.83)

也会返回True。并且具有比Currency更准确的准确度。 CDec documentation.

enter image description here