在Visual Basic 6.0中自动类型转换

时间:2009-03-15 12:51:04

标签: vb6 types

当我们在Visual Basic 6.0中将float转换为整数时,它如何使小数部分变圆?我正在谈论自动类型转换。

如果我们指定

Dim i as Integer
i=5.5
msgbox i

它会打印什么? 5或6 ??

几个月前我得到了“5”。有一天它开始给我6个! 有什么想法是错的吗?微软是否发布了一些补丁来解决问题?

更新:5.5转换为6但8.5到8!

更新2:添加CInt没有任何区别。 CInt(5.5)给出6,而Cint(8.5)得到8!有点喜欢的行为。我应该尝试类似楼层(x + 0.49);

5 个答案:

答案 0 :(得分:7)

更新:经过一些谷歌搜索后,我遇到了the following article

  

这不是“bug”,而是VB的方式   旨在工作。它使用的东西   如果被称为银行家的四舍五入   这个数字恰好以5和你结束   想要绕到前面的位置   如果是5,它会向下舍入数字   5的前面的数字   位置是均匀的和圆形的   除此以外。它应该保护   反对使用重复计算   四舍五入的数字,以便答案不是   总是偏向上方。有关这方面的更多信息   问题比你可能想知道的,   看到这个链接

     

http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q196652

这解释了(明显的)奇怪的行为:

Cint(5.5) 'Should be 6'
Cint(8.5) 'Should be 8'

旧更新: 也许您应该更明确:使用CInt,而不是简单地将浮点数赋给整数。 E.g:

Dim i as Integer
i = CInt(5.5)
MsgBox i

答案 1 :(得分:7)

部分内容在VB6帮助中:主题类型转换函数。不幸的是,它是MSDN网站上VB6 documentation内没有的主题之一,但是如果您已经安装了VB6的帮助,它就会在那里。

  

当小数部分恰好为0.5时, CInt CLng 始终将其四舍五入为最接近的偶数。例如,0.5轮到0轮,1.5轮到2轮。 CInt CLng 修复 Int 函数,它截断而不是舍入数字的小数部分。此外,修复 Int 始终返回与传入的类型相同的值。

隐式类型强制 - a.k.a。"evil type coercion (PDF)" - 从浮点数到整数使用与 CInt CLng 相同的舍入规则。在手册中的任何位置似乎都没有记录此行为。

如果你想在小数部分> = 0.5时向上舍入,否则向下舍入,一个简单的方法是

 n = Int(x + 0.5)

我的头部的顶部,这是Mike Spross的RoundNumber :)的简短版本,它取代了VB6 Round函数。

 'Written off the top of my head, seems to work. 
Public Function RoundNumber(ByVal value As Double, Optional PlacesAfterDecimal As Integer = 0) As Double
  Dim nMultiplier As Long
  nMultiplier = 10 ^ PlacesAfterDecimal
  RoundNumber = Int(0.5 + value / nMultiplier) * CDbl(nMultiplier)
End Function

示例输出:

Debug.Print RoundNumber(1.6)       '2'
Debug.Print RoundNumber(-4.8)      '-5'
Debug.Print RoundNumber(101.7)     '102'
Debug.Print RoundNumber(12.535, 2) '12.54'

答案 2 :(得分:1)

改变后的行为听起来确实令人担忧,但是正确的答案是6.在Wikipedia, Rounding上向下滚动到“Round to even method”以获得解释。

答案 3 :(得分:1)

正如其他人已经指出的那样,你所看到的“怪异行为”是由于VB6在舍入小数值时使用Banker's Rounding这一事实。

  

更新2:添加CInt没有   区别。 CInt(5.5)给出6和   Cint(8.5)给出8 !!

这也很正常。在执行转换之前,CInt总是进行舍入(再次使用Banker的舍入方法)。

如果你有一个带小数部分的数字并且只想截断它(忽略小数点后面的部分),你可以使用FixInt函数:

Fix(1.5) = 1
Fix(300.4) = 300
Fix(-12.394) = -12

IntFix的工作方式相同,只是它将负数舍入到下一个最低负数:

Int(1.5) = 1
Int(300.4) = 300
Int(-12.394) = -13

如果你真的想根据大多数人熟悉的规则围绕编号,你必须编写自己的函数来完成它。下面是一个示例舍入,当小数部分大于或等于.5时将向上舍入,否则向下舍入:


编辑请参阅MarkJ's answer了解此功能更简单(可能更快)的版本。


' Rounds value to the specified number of places'
' Probably could be optimized. I just wrote it off the top of my head,'
' but it seems to work.'
Public Function RoundNumber(ByVal value As Double, Optional PlacesAfterDecimal As Integer = 0) As Double

    Dim expandedValue As Double
    Dim returnValue As Double
    Dim bRoundUp As Boolean

    expandedValue = value
    expandedValue = expandedValue * 10 ^ (PlacesAfterDecimal + 1)
    expandedValue = Fix(expandedValue)

    bRoundUp = (Abs(expandedValue) Mod 10) >= 5

    If bRoundUp Then
        expandedValue = (Fix(expandedValue / 10) + Sgn(value)) * 10
    Else
        expandedValue = Fix(expandedValue / 10) * 10
    End If

    returnValue = expandedValue / 10 ^ (PlacesAfterDecimal + 1)
    RoundNumber = returnValue

End Function

<强>实施例

Debug.Print RoundNumber(1.6)       '2'
Debug.Print RoundNumber(-4.8)      '-5'
Debug.Print RoundNumber(101.7)     '102'
Debug.Print RoundNumber(12.535, 2) '12.54'

答案 4 :(得分:0)

VB6 Round()函数使用Banker's Rounding方法。 MS KB文章225330(http://support.microsoft.com/kb/225330)通过将Office 2000中的VBA与Excel的本机行为进行比较来间接地讨论这个问题并以这种方式描述:

  

当具有偶数整数的数字以.5结尾时,Visual Basic将数字(向下)舍入到最接近的偶数整数。 [...]对于以.5结尾的数字,[在VBA和Excel之间]的差异,与其他小数相同。

如果您需要不同的行为,我担心您必须自己指定。