VB6 Log10函数

VB6 Log10函数,vb6,ieee-754,Vb6,Ieee 754,我的第一个问题,请温柔一点 我有一个Log10函数,我非常满意 Public Function Log10(ByVal n As Long) As Long Select Case n Case Is >= 1000000000: Log10 = 9 Case Is >= 100000000: Log10 = 8 Case Is >= 10000000: Log10 = 7 Case Is >= 1

我的第一个问题,请温柔一点

我有一个Log10函数,我非常满意

Public Function Log10(ByVal n As Long) As Long

    Select Case n
        Case Is >= 1000000000: Log10 = 9
        Case Is >= 100000000: Log10 = 8
        Case Is >= 10000000: Log10 = 7
        Case Is >= 1000000: Log10 = 6
        Case Is >= 100000: Log10 = 5
        Case Is >= 10000: Log10 = 4
        Case Is >= 1000: Log10 = 3
        Case Is >= 100: Log10 = 2
        Case Is >= 10: Log10 = 1
        Case Else: Log10 = 0
    End Select

End Function
然而,当为这个函数创建一个测试时(我知道它很简单,我知道它可以工作-QA等等),它看起来是这样的

Public Const LONG_MAX As Long = 2147483647

Public Sub testLog10()

    Dim i As Long
    Dim a As Long
    Dim b As Long

    For i = 1 To LONG_MAX
        DoEvents
        a = Log10(i)
        b = Int(Log(i) / Log(10))
        Debug.Assert a = b
    Next

End Sub
Private Function Log10(ByVal n As Long) As Long
    Dim d As Double
    d = Log(n) / Log(10)
    Log10 = Int(CStr(d))
End Function
A通常不等于B,正如你所能想象的,这是一个相当令人惊讶的现象,因为主对数恒等式应该始终保持不变。如果你把它抽象成一个函数

Private Function Log10(ByVal n As Long) As Long
    Dim d As Double
    d = Log(n) / Log(10)
    DblLog10 = Int(d)
End Function
然后你会看到,当n=10,d=1,这是正确的。但是,当它转换为int时,它会将其截断为零。对于那些感兴趣的人来说,修复没有什么区别(无论如何也不应该有区别))这是可以修复的

Private Function Log10(ByVal n As Long) As Long
    Dim d As Double
    d = Log(n) / Log(10) + 0.000000001
    DblLog10 = Int(d)
End Function
这意味着double的内部表示,虽然在VB6IDE中显示为一,但并不是这样的


不管怎样,问题是:我是错过了什么,还是仅仅是我必须做的事情。这并不重要,因为这是一个测试函数,而不是生产代码。最重要的是,我感兴趣。

VB6 Double是一种二进制浮点数类型。当你做算术时,你会得到舍入误差。别担心

你听起来像一个数学人,所以你应该了解更多。如果你在编程数字的东西,它会很有用。试试看这个。这是一篇c#文章,但在VB6中也有相同的原则


您可以通过如下方式将结果临时转换为
字符串来规避
双重
特性

Public Const LONG_MAX As Long = 2147483647

Public Sub testLog10()

    Dim i As Long
    Dim a As Long
    Dim b As Long

    For i = 1 To LONG_MAX
        DoEvents
        a = Log10(i)
        b = Int(Log(i) / Log(10))
        Debug.Assert a = b
    Next

End Sub
Private Function Log10(ByVal n As Long) As Long
    Dim d As Double
    d = Log(n) / Log(10)
    Log10 = Int(CStr(d))
End Function
不过,如果要在紧密循环中调用函数,这对性能有轻微影响