【问题标题】:VB6 floating point computation issueVB6浮点计算问题
【发布时间】:2017-05-27 04:07:38
【问题描述】:

这是浮点计算问题(我认为)。

这是我在某处找到的 2 轮函数。

它们在代码中看起来非常相似,但是当我运行它时,我得到了 2 个不同的结果。

在此示例中,当运行此代码时,值为 87.13225 和精度 4:

a = 87.1322

b = 87.1323

谁能解释发生了什么?

Private Sub Form_Load()
    Dim a#
    Dim b#
    a = Round1(87.13225, 4) '87.1322
    b = Round2(87.13225, 4) '87.1323
End Sub

Private Function Round1(ByVal value#, ByVal vPrecision%)
    Round1 = Fix((value + Sgn(value) / 10 ^ vPrecision / 2) * _
                10 ^ vPrecision) _
            / 10 ^ vPrecision
End Function

Private Function Round2(ByVal value#, ByVal vPrecision%)
    Dim a#
    a = (value + Sgn(value) / 10 ^ vPrecision / 2) * 10 ^ vPrecision
    Round2 = Fix(a) / 10 ^ vPrecision
End Function

【问题讨论】:

  • 这可能会有所帮助:Intermediate Floating-Point Precision
  • 浮点运算并不十分精确。我可以写一个详细的答案来解释为什么会在你的代码中发生这种情况,但它很可能很复杂,而且比你真正想知道的要多。更重要的是,它不会帮助您解决问题。说到这里,您要解决的问题是什么?当您以不同的方式执行浮点运算时,永远无法保证您会得到相同的结果。另见:docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
  • deblocker,Cody:谢谢你的回答。

标签: vb6 floating


【解决方案1】:

我相信,您的部分问题涉及类型转换。由于您传递的文字参数未定义为双精度参数,我相信它们是作为单精度参数传递的,然后转换为双精度参数,这可能会影响您的结果。尝试将文字作为 87.12335# 传递给每个方法。此外,您没有定义任何一个函数的输出类型,所以我相信它会返回变体。我相信这两种方法都应该以“ As Double”结尾

最后,您为什么要尝试重新发明轮子? VB6 能够进行两种不同的舍入。 Banker's Rounding 是 VB6 的默认舍入方案。这让我很吃惊,于是我写了会计软件。银行家的四舍五入总是四舍五入到最接近的偶数,所以你的两个结果都应该是 87.1234。在银行家的四舍五入中,87.12345 也将四舍五入为 87.1234。如果你想要舍入总是从零开始舍入,这是我更熟悉的,你应该使用各种格式方法,即 FormatNumber、Format$ 等。上面引用的页面上有一个链接解释了这一点进一步。当我发现这种差异时,我根据客户的喜好使用银行家四舍五入或我称之为标准四舍五入的方法制定了自己的四舍五入程序。

【讨论】:

  • 第一段的推测不正确。 # 类型后缀表示 Double,因此参数 do 有效地以 As Double 结尾。这意味着参数不是作为 Singles 传递的,而是作为 Doubles 传递的,因为这是它们的显式类型。现在,确实,经典的 VB 将文字存储在它们适合的最低精度类型中,因此这些文字实际上可能是 Singles,但是当它们被传递给将其参数作为 Doubles 的函数时会发生类型提升,并且有那里没有精度损失。 (这是一个扩大的转换。)
  • 感谢您的回答。我也想使用银行家的四舍五入。但这是我们 20 年的客户代码,所以我想保持它的逻辑,而不是重新发明轮子。对于我的问题,@deblocker 的回答是正确的。
猜你喜欢
  • 1970-01-01
  • 2021-09-06
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-15
  • 1970-01-01
相关资源
最近更新 更多