Непонимание типа данных Long в VBA - PullRequest
3 голосов
/ 25 ноября 2008

Из справки об ошибке переполнения в VBA есть следующие примеры:

Dim x As Long
x = 2000 * 365 ' gives an error

Dim x As Long
x = CLng(2000) * 365 ' fine

Я бы подумал, что, поскольку предполагается, что тип данных Long может содержать 32-разрядные числа, первый пример будет работать нормально.

Я спрашиваю это, потому что у меня есть такой код:

Dim Price as Long
Price = CLng(AnnualCost * Months / 12)

, и это вызывает ошибку переполнения, когда AnnualCost равно 5000, а Months равно 12.

Чего мне не хватает?

Ответы [ 3 ]

12 голосов
/ 25 ноября 2008

2000 и 365 - целочисленные значения. В VBA целые числа представляют собой 16-битные типы со знаком, когда вы выполняете арифметику с двумя целыми числами, арифметика выполняется в 16-битной форме. Поскольку результат умножения этих двух чисел превышает значение, которое может быть представлено 16 битами, вы получаете исключение. Второй пример работает, потому что первое число сначала преобразуется в 32-разрядный тип, а затем выполняется арифметика с использованием 32-разрядных чисел. В вашем примере арифметика выполняется с 16-разрядными целыми числами, а затем результат преобразуется в long, но в этот момент уже слишком поздно, переполнение уже произошло. Решение состоит в том, чтобы сначала преобразовать один из операндов в умножении в long:

Dim Price as Long
Price = CLng(AnnualCost) * Months / 12
2 голосов
/ 25 ноября 2008

Проблема в том, что умножение происходит внутри скобок перед преобразованием типов. Вот почему вам нужно сначала преобразовать хотя бы одну из переменных в Long, а затем умножить их.

Предположительно, вы определили переменные как Integer. Вы можете рассмотреть возможность использования Long вместо Integer, отчасти потому, что у вас будет меньше проблем с переполнением, а также потому, что Longs вычисляют (немного) быстрее, чем Integer на 32-битных машинах. Longs занимают больше памяти, но в большинстве случаев это не проблема.

1 голос
/ 28 декабря 2008

В VBA литералы по умолчанию целочисленные (как уже упоминалось). Если вам нужно навязать им больший тип данных, вы можете изменить их, как в примере выше, или просто добавить символ объявления типа. (Список здесь: http://support.microsoft.com/kb/191713) Тип для Long - "&", поэтому вы можете просто сделать:

Price = CLng(AnnualCost * Months / 12&)

И 12 будет переделан как длинный. Однако, как правило, рекомендуется избегать литералов и использовать константы. В этом случае вы можете ввести константу в ее объявлении.

Const lngMonths12_c as Long = 12
Price = CLng(AnnualCost * Months / lngMonths12_c)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...