VBA中使用整数计算算术表达式时出现溢出错误

VBA中使用整数计算算术表达式时出现溢出错误,vba,Vba,以下计算结果为32760,一个整数: Debug.Print (20 * 1638 - 1) 但这会引发溢出错误: Dim t as Integer t = 1639 Debug.Print (20 * t - 1) 这似乎隐含地希望返回一个Integer值,因为如果我执行以下任一操作,就会避免错误 Dim t尽可能长或Debug.print(20*CLng(t)-1)或Debug.print(20*t-1) 这种行为有记录吗 我的假设准确吗?也就是说,整数的算术意味着一个整数返回值,简单地

以下计算结果为
32760
,一个整数:

Debug.Print (20 * 1638 - 1)
但这会引发溢出错误:

Dim t as Integer
t = 1639
Debug.Print (20 * t - 1)
这似乎隐含地希望返回一个
Integer
值,因为如果我执行以下任一操作,就会避免错误

Dim t尽可能长
Debug.print(20*CLng(t)-1)
Debug.print(20*t-1)

这种行为有记录吗


我的假设准确吗?也就是说,整数的算术意味着一个整数返回值,简单地在等式中引入一个
Long
Double
值可以避免错误?

如果我的逻辑正确,
Dim
或“Dimension”是告诉应用程序您希望使用某种类型的变量的一种方式,这种类型属于一定数量的“位”(内存)

这将保留系统内存的一部分,根据您在代码中指示的变量类型,该部分内存已分配一定数量的位。这些位然后定义了多少(如果你熟悉C++或类似的,那么你可能已经知道所有这些……)/P> 在VBA中,整数是16位的,是有符号整数,这意味着我们也可以存储负值,因此限制为32767,因为这是16位可以实现的最大数字:

(通常一个变量可以容纳2^n,其中n=位数)


需要首先将
t
乘以20,得出32780的数字:

20 * t = 20 * 1639 = 32,780
32,780 = 1000000000001100 (Binary)
超出了
整数
数据类型的位限制。此时,系统在有机会继续其余的计算之前抛出一个错误,因为它试图乘
t
,同时仍在分配的内存地址中,仅为该地址保留了16位内存

此外,不将
t
声明为类型将强制VBA默认为类型
Variant
,这将评估
t
在计算运行时需要分配更多内存,并自动将其推入
Long
边界


更新:VBA似乎只允许返回值方程式中的变量保留最高数量的位,如本例所示:

Sub SO()

Dim t As Integer, c As Long

t = 1639
c = 20

Debug.Print (20 * (t - 1))  '// No Error
Debug.Print (c * (t - 1))   '// No Error
Debug.Print ((c * t) - 1)   '// No Error

c = (20 * t - 1)            '// Error
Debug.Print (20 * t - 1)    '// Error

End Sub

虽然我不认为这在任何地方都有记录,但这会让人相信VBA将内存使用限制为变量在任何时候使用的最高位数。

这是您链接到的一个很好的答案,谢谢@TimWilliams。对我来说也很有用……可能还值得注意的是,VBA将所有
Integer
值转换为
Long
类型,因此在
Long
上使用
Integer
并没有任何真正的好处(我可以想到)@SOofWXLS AFAIK这是对长数据类型的内部转换,如果您试图将该结果作为整数放入类型化变量
,则会导致溢出。对于我这里的OP,当对所有整数类型的数据进行数学运算时,VBA假定隐含的结果也是
integer
。这在这方面很奇怪。@David Zemens我非常感谢21k+的代表,你已经知道了其中的大部分内容-这主要是为了VBA社区的利益,他们在内存分配和OOP方面没有那么“混乱”。+1所有这些都是非常好的信息!它本身并没有回答这个问题(我知道为什么long会导致整数溢出,但我不确定为什么某些算术会导致独立于类型容器的溢出,即,乘以整数x整数意味着整数输出,即使将结果分配给能够接受long的属性!)但对于将来具有类似q的其他人来说仍然是有用的。谢谢@DavidZemens我在我的答案中添加了更多的内容,我认为最终在没有任何官方文件的情况下,我们所能做的就是对原因进行“有根据的猜测”。虽然很有趣,但我希望能得到更多的信息-好问题!调试语句中的圆括号太多,或者,圆括号的放置方式改变了操作顺序:
(20*t-1)
==
((20*t)-1)
(20*t-1)
将抛出错误,因为所讨论的隐含输出类型。问题是,仅由整数组成的表达式的乘积即使分配给长/双容器也可能导致溢出,因为隐含输出的类型将是
Integer
——请尝试:
Dim val as Long:val=(20*1639*1)
。是的,我明白-我想我只是误解了这个问题,并且有点偏离正题,哎呀!
20 * t = 20 * 1639 = 32,780
32,780 = 1000000000001100 (Binary)
Sub SO()

Dim t As Integer, c As Long

t = 1639
c = 20

Debug.Print (20 * (t - 1))  '// No Error
Debug.Print (c * (t - 1))   '// No Error
Debug.Print ((c * t) - 1)   '// No Error

c = (20 * t - 1)            '// Error
Debug.Print (20 * t - 1)    '// Error

End Sub