Сравнение с плавающей точкой в ​​VB6 - PullRequest
3 голосов
/ 07 сентября 2010

Каков наилучший способ проверки двух одинарных на равенство в VB6?

Я хочу проверить два одинарных значения на равенство до 7 значащих цифр.

Эта статья MSDN рекомендует использовать что-то вроде

If Abs(a - b) <= Abs(a / 10 ^ 7) Then
    valuesEqual = True
End If

Однако, это может не сработать для определенных значений, например,

Public Sub Main()

    Dim a As Single
    Dim b As Single

    a = 0.50000005
    b = 0.50000014

    Debug.Print "a = " & a
    Debug.Print "b = " & b
    Debug.Print "a = b: " & (a = b)
    Debug.Print "SinglesAreEqual(a, b): " & SinglesAreEqual(a, b)

    // Output:
    // a = 0.5000001
    // b = 0.5000001
    // b = b: False
    // SinglesAreEqual(a, b): False

End Sub

Private Function SinglesAreEqual(a As Single, b As Single) As Boolean

    If Abs(a - b) <= Abs(a / 10 ^ 7) Then
        SinglesAreEqual = True
    Else
        SinglesAreEqual = False
    End If

End Function

Самый простой способ получения нужного мне результата - преобразоватьзначения в строки, но кажется ужасно уродливым:

Private Function SinglesAreEqual(a As Single, b As Single) As Boolean

    SinglesAreEqual = (Str$(a) = Str$(b))

End Function

Есть ли лучшие способы?

Ответы [ 3 ]

3 голосов
/ 07 сентября 2010

Я поддерживаю приложение CAD / CAM, и мне постоянно приходится иметь дело с числами с плавающей запятой.У меня есть функция, которую я вызываю fComp, и я передаю значение с плавающей запятой, когда мне нужно проверить на равенство.fComp вызывает функцию округления с заданным уровнем точности.Для нашей системы я округляю до 6 знаков после запятой.Ваше может потребоваться выше или сойти с рук ниже, это зависит от приложения.

Функция fComp существует, поэтому у меня есть одна возможность изменить коэффициент округления, используемый в этих вычислениях.Это оказалось полезным пару лет назад, когда мы начали производство высокоточных станков.

Public Function pRound(ByVal Value As Double, ByVal Power As Double) As Double
    Dim TempValue As Double
    Dim tSign As Double
    TempValue = Value
    tSign = TempValue
    TempValue = Abs(TempValue)
    TempValue = TempValue * 10 ^ (Power * -1)
    TempValue = Fix(TempValue + 0.5)
    TempValue = TempValue / 10 ^ (Power * -1)
    pRound = TempValue * Sign(tSign)
End Function

Чтобы округлить до шестого знака после запятой, вы идете

RoundedNumber = pRound (MyValue, -6)

Отрицательный справа от десятичного знака положительный клевый.

2 голосов
/ 08 сентября 2010

Не думаю, что вы можете использовать тип данных single для стольких значимых цифр. Вам нужно будет использовать double вместо:

Dim a As Single
Dim s As String

s = "0.50000005"
a =  0.50000005

Debug.Print s & " " & a

Вышеуказанные выходы:

0.50000005
0.5000001
2 голосов
/ 08 сентября 2010

Вместо округления и проверки на равенство вы можете взять разность двух чисел и сравнить ее с коэффициентом

If Abs(a - b) < 0.000001 Then

Вы можете настроить 0.000001 на любое необходимое разрешение

...