【问题标题】:Overflow when multiplying Integers and assigning to Long将整数相乘并分配给 Long 时溢出
【发布时间】:2013-06-26 08:56:43
【问题描述】:

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

MsgBox 24 * 60 * 60

这是为什么?

这也失败了:

Dim giveTime  As Long 
giveTime  = 24 * 60 * 60

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

【问题讨论】:

  • 更进一步。 - 如果我将 msgbox 26 * 60 ^ 2 放在即时窗口中,则没有问题。这是优先顺序问题吗?这似乎不太可能......
  • 那是因为 ^ 运算符返回一个 Double,这回避了我在下面的回答中描述的问题。

标签: vba integer-overflow


【解决方案1】:

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

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

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

结果 = number1 * number2

[...]

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

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

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

帮助文件也这样说:

如果 [...] result 的数据类型是整数 variant 超出其合法范围 [...] 那么 result [...] 转换为 Long 变体。

强调我的。现在这个小规则听起来像是常识,任何人都会合理地假设它适用于你的情况。但是您的数字是整数类型,而不是 Variant/Integer,因此 VBA 不适用此规则!对我来说绝对没有意义,但这就是事实,这就是文档所说的。

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

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

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


您在 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

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

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

【讨论】:

  • 当然是个怪癖!那么,Variant/Integer 和 Integer 之间有什么区别?我假设一个在代码中声明,另一个在内部声明?
  • 或x = [24 * 60 * 60]
  • 对。好吧,[] 方括号是Evaluate method 的简写。因此,您正在调用 Excel 解释器来评估 VBA 中的表达式。听起来如果重复执行会增加很多开销,但我想如果偶尔使用也可以。
【解决方案2】:

在每个数字后面加上#。它将每个数字定义为双精度数。可以将其想象为,每个数字都作为临时变量放入内存中进行计算。 如果您定义每个数字,它将为计算留出足够的空间。

例如:

暗×长

x = 24# * 60# * 60#

或24&'表示长

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 2011-02-12
    • 2023-03-15
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多