乘以整数并分配给Long时溢出

时间:2013-06-26 08:56:43

标签: vba integer-overflow

如果我在即时窗口中键入以下内容,则会出现运行时错误“6”:溢出。

MsgBox 24 * 60 * 60

这是为什么?

这也失败了:

Dim giveTime  As Long 
giveTime  = 24 * 60 * 60

这是为什么? giveTime被声明为Long类型,因此24×60×60 = 86400应该适合。

2 个答案:

答案 0 :(得分:27)

这是一个非常奇怪的VBA怪癖。我很惊讶我从未碰到过这个。

Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow. 
x = 32768 + 1 ' Works fine!

所以看起来*+运算符在前两个示例中返回一个Integer。果然,在*运算符的帮助文件中(类似于+运算符):

  

结果 = number1 * number2

     

[...]

     

结果的数据类型通常与最精确的表达式相同。

默认情况下,您的文字24,60和60都是Integer类型,因此您的*(或+)运算符返回一个Integer,它会溢出,因为结果大于32,767。

但是,上面第三个例子中的文字32,768默认为Long类型(因为它太大而不能成为整数),因此+返回Long;没有溢出。

帮助文件也说明了这一点:

  

如果结果的数据类型是整数变种,其溢出其合法范围[...]则结果被转换为Long变体。

强调我的。现在这个小规则听起来像常识,任何人都会合理地认为它适用于你的情况。但是你的数字是Integer类型,而不是Variant / Integer,所以VBA不适用这个规则!对我来说完全没有意义,但就是这样,这就是文档所说的。

解决方案:使*运算符的一个参数的类型比Integer更精确(例如Long),问题就会消失。

x = CLng(24) * 60 * 60 ' Result is Long, works fine.

事实上,这可能就是为什么我从来没有碰到这个怪癖,我养成了将所有的Integer变量声明为Long的习惯,除非特别关注Longs而不是Integers会导致问题内存使用或执行时间(几乎不是这种情况)。当然,这对于操作小于32,768的文字的情况没有帮助,因为它们默认为Integer类型。


你在a comment询问Variant / Integer是什么。 Variant基本上是任何其他数据类型的容器类型。在使其包含整数的特定情况下:

Dim a As Variant ' a is now Empty
a = CInt(32767) ' a is now Variant/Integer
x = a + 1 ' works fine

但如上所述,普通的旧整数会触发溢出错误:

Dim b As Integer
b = 32767
x = b + 1 ' overflow

答案 1 :(得分:2)

每个号码后,放置#。它将每个数字定义为double。可以把它想象成,每个数字都放在内存中,作为临时变量的计算。 如果定义每个数字,它将为计算留出足够的空间。

例如:

Dim x As Long

x = 24#* 60#* 60#

或24& '表示长