当我们在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);
答案 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的舍入方法)。
如果你有一个带小数部分的数字并且只想截断它(忽略小数点后面的部分),你可以使用Fix
或Int
函数:
Fix(1.5) = 1
Fix(300.4) = 300
Fix(-12.394) = -12
Int
与Fix
的工作方式相同,只是它将负数舍入到下一个最低负数:
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之间]的差异仅,与其他小数相同。
如果您需要不同的行为,我担心您必须自己指定。