【问题标题】:vba Fix function, double comparisons returning unexpected valuevba 修复函数,双重比较返回意外值
【发布时间】:2015-09-02 17:22:19
【问题描述】:

修复 vba 中的函数在传递 3 时返回 2:

Debug.Print (Fix(Log(1000) / Log(10)))

--> 这会打印 2 而不是 3

这是为什么呢?

【问题讨论】:

  • 嗯 - 将其插入Wolfram Alpha,结果是“3”,但看看数字线的视觉效果,它是“2”......我想知道这是否也是 Excel 得到的?
  • 我不明白您要求查看数字线视觉效果的要求。
  • 这可能无助于获得答案,但如果您单击链接,您是否看不到数字行?此外,int(log(1000)/log(10)) 也提供了2。奇怪的。为什么要使用Fix()

标签: excel vba


【解决方案1】:

Log(1000)/Log(10) 或 6.90775527898214 ÷ 2.30258509299405 应该等于 3 但似乎 15 位浮点精度正在生成 15 digit precision floating point error 并且 Fix 正在删除所有小数。如果您Round 到小数点后 15 位以消除无限小的错误,您将收到 3 作为答案。

?round(log(1000)/log(10), 15)

【讨论】:

    【解决方案2】:
    Debug.Print Log(1000)   '6.90775527898214
    Debug.Print Log(10)     '2.30258509299405
    
    6.90775527898214
       /
    2.30258509299405
    =2.999999999999996      'VBA is convering this to '3#'
    
    Debug.Print Fix(3#)     '2
    Debug.Print Round(Fix(Log(1000) / Log(10)))     '2
    Debug.Print Round(Round(Fix(Log(1000)) / Round(Log(10))))   '3 (This is what you want)  
    Debug.Print (Round(Fix(Log(1000)) / Round(Log(10))))        '3 (Or may be only this)
    

    【讨论】:

      【解决方案3】:

      对 Log 函数进行调试:

      Public Sub Test()
          Dim number As Double
          number = Log(1000)
          Debug.Print number
      End Sub
      

      打印:6.90775527898214

      Public Sub Test()
          Dim number As Double
          number = Log(10)
          Debug.Print number
      End Sub
      

      打印:2.30258509299405

      当你除以那些你得到的:2.(很多 9)并且在那个数字上调用 Fix 会给你 2 而不是 3。

      【讨论】:

        【解决方案4】:

        嗯 - 我认为这是 VB 处理日志的方式与工作表函数处理日志的方式。使用这个,我得到3:

        Debug.Print fix(worksheetfunction.log10(1000)/worksheetfunction.log10(10))

        我记得我在使用 Logs 时遇到过类似问题,并在 SO 上询问过,所以这里可能是相关问题。

        【讨论】:

          【解决方案5】:

          当您使用浮点数时(单一数据类型(Visual Basic) 和 Double 数据类型 (Visual Basic)),记住它们是 存储为二进制分数。这意味着他们无法掌握准确的 表示任何不是二进制分数的量(的 形式 k / (2 ^ n) 其中 k 和 n 是整数)。例如,0.5 (= 1/2) 和 0.3125 (= 5/16) 可以保持为精确值,而 0.2 (= 1/5) 而 0.3 (= 3/10) 只能是近似值。

          https://msdn.microsoft.com/en-us/library/ae382yt8.aspx

          所以我所做的是创建了另一个修复函数,如下所示: '修复有问题

          Public Function FixModified(ByVal x As Double, ByVal threshold As Double)
              If Fix(x) = x Then
                  FixModified = x
              ElseIf Fix(x) + 1 - x < threshold Then
                  FixModified = Fix(x) + 1
              Else
                  FixModified = Fix(x)
              End If
          End Function
          

          我现在通过的阈值是 0.000000000001,它按预期工作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-10-23
            • 2022-01-09
            • 1970-01-01
            • 1970-01-01
            • 2015-01-06
            • 2014-12-08
            • 2018-01-24
            • 1970-01-01
            相关资源
            最近更新 更多