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

Exc*_*eha 11 vba integer-overflow

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

MsgBox 24 * 60 * 60
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

这也失败了:

Dim giveTime  As Long 
giveTime  = 24 * 60 * 60
Run Code Online (Sandbox Code Playgroud)

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

Jea*_*ett 27

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

Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow. 
x = 32768 + 1 ' Works fine!
Run Code Online (Sandbox Code Playgroud)

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

result = number1*number2

[...]

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

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

但是,上面第三个例子中的字面值32,768默认为Long类型(因为它太大而不能成为Integer)所以+返回Long; 没有溢出.

帮助文件也说:

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

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

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

x = CLng(24) * 60 * 60 ' Result is Long, works fine.
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

Dim b As Integer
b = 32767
x = b + 1 ' overflow
Run Code Online (Sandbox Code Playgroud)

  • 对。好吧,`[]` 方括号是 [`Evaluate` 方法的简写](http://office.microsoft.com/client/helppreview14.aspx?AssetId=HV080005401&lcid=2057&NS=EXCEL.DEV&Version=14&tl=2&respos=0&CTT =1&queryid=0b704676-cdcb-458a-b300-1bf8775c4ed3)。因此,您正在调用 Excel 解释器来计算 VBA 中的表达式。如果重复进行,听起来会增加很多开销,但我想如果偶尔使用也没关系。 (2认同)

小智 5

在每个数字之后,放置#。它将每个数字定义为双精度数。把它想象成,每个数字都被放入内存中以作为一种临时变量进行计算。如果您定义每个数字,它将为计算留出足够的空间。

例如:

暗 x 长

x = 24# * 60# * 60#

或 24&' 表示长