Я часто вижу вопросы, связанные с ошибками Overflow
с vba.
Мой вопрос, почему использовать integer
переменную декларацию вместо того, чтобы просто определить все числовые переменные ( за исключением double
и т.д.), как long
?
Если вы не выполняете операцию, подобную циклу for, где вы можете гарантировать, что значение не превысит ограничение 32 767, это повлияет на производительность или что-то еще, что будет диктовать отсутствие использования long
?
Целочисленные переменные сохраняются как 16-разрядные (2-байтовые) номера
Длинные (длинные целочисленные) переменные сохраняются как подписанные 32-разрядные (4-байтовые) номера
Таким образом, преимущество в сокращении объема памяти. Целое число занимает половину памяти, которая длится долго. Теперь мы говорим о 2 байтах, поэтому это не будет иметь особого значения, если вы не храните TON целых чисел.
НО в 32- битной системе 16-битное целое число беззвучно преобразуется в длинный, без использования большего диапазона чисел для работы. Переполнение все еще происходит, и требуется столько же памяти. Производительность может даже пострадать, потому что тип данных должен быть преобразован (на очень низком уровне).
Не ссылка, которую я искал, но....
Я понимаю, что базовый движок VB преобразует целые числа в длинные, даже если он объявлен как целое. Поэтому можно отметить небольшое снижение скорости. Я верил в это какое-то время и, возможно, это также объясняется тем, что было сделано выше, я не просил рассуждать.
Это ссылка, которую я искал.
Короткий ответ, в 32-битных системах 2 байтовых целых числа преобразуются в 4 байта Longs. Нет другого способа, чтобы соответствующие биты правильно выстраивались в линию для любой формы обработки. Рассмотрим следующее
MsgBox Hex(-1) = Hex(65535) ' = True
Очевидно, что -1 не равен 65535, но компьютер возвращает правильный ответ, а именно "FFFF" = "FFFF",
Однако если бы мы принудили -1 к первому долгу, мы бы получили правильный ответ (65535, превышающий 32k, автоматически длинный)
MsgBox Hex(-1&) = Hex(65535) ' = False
"FFFFFFFF" = "FFFF"
Как правило, в VBA нет смысла объявлять "как целое" в современных системах, за исключением, возможно, для некоторых устаревших API, которые ожидают получить Integer.
И наконец я нашел документацию msdn, которую я действительно искал.
Традиционно программисты VBA использовали целые числа для хранения небольших чисел, потому что им требовалось меньше памяти. Однако в последних версиях VBA преобразует все целочисленные значения в тип Long, даже если они объявлены как тип Integer. Таким образом, больше нет преимущества производительности для использования переменных Integer; Фактически, длинные переменные могут быть немного быстрее, потому что VBA не нужно их преобразовывать.
Итак, в итоге, в наши дни почти нет оснований использовать тип Integer
. Если вам не нужно взаимодействовать со старым вызовом API, который ожидает 16-битный int.
Следует отметить, что некоторые старые функции API могут ожидать параметры, которые представляют собой 16-битные (2-байтовые) целые числа, и если вы находитесь на 32-битном и пытаетесь передать Integer (это уже 4-байтовый) по ссылке он не будет работать из-за разницы в длине байтов.
Благодаря Vba4All для указания этого.
Как отмечено в других ответах, реальная разница между int и long - это размер его пространства памяти и, следовательно, размер числа, которое он может удерживать.
вот полная документация по этим типам данных http://msdn.microsoft.com/en-us/library/office/ms474284(v=office.14).aspx
a Integer - 16 бит и может представлять значение от -32,768 до 32,768
a Длинный - 32 бита и может представлять -2,147,483,648 до 2,147,483,648
и есть LongLong, который имеет 64 бита и может обрабатывать как 9 pentilion
Одна из самых важных вещей, которые следует помнить об этом, - это то, что типы данных различаются как языком, так и операционной системой/платформой. В вашем мире VBA длинное 32 бита, но в С# на 64-битном процессоре длинное 64 бит. Это может привести к значительной путанице.
Хотя VBA не поддерживает его, когда вы переходите на любой другой язык в .net или java или другом, я предпочитаю использовать системные типы данных int16, int32 и int64, что позволяет мне намного более прозрачно относиться к значениям, которые могут храниться в этих типах данных.
У VBA много исторического багажа.
An Integer
имеет ширину 16 бит и является хорошим цифровым типом по умолчанию, когда были распространены 16-битные архитектуры/размеры слов.
A Long
имеет ширину 32 бита и (IMO) следует использовать там, где это возможно.
Несмотря на то, что этому сообщению четыре года, мне было интересно об этом и провела несколько тестов. Самое главное отметить, что кодер должен ВСЕГДА объявить переменную как ЧТО-ТО. Необъявленные переменные явно выполняли худшие (необъявленные технически Variant
)
Long
работал быстрее, поэтому я должен думать, что рекомендация Microsoft всегда использовать Long
вместо Integer
имеет смысл. Я предполагаю то же самое, что и у Byte
, но большинство кодеров не используют это.
РЕЗУЛЬТАТЫ НА ОКОНЧАТЕЛЬСТВЕ 64 БИТ WINDOWS 10
Используемый код:
Sub VariableOlymics()
'Run this macro as many times as you'd like, with an activesheet ready for data
'in cells B2 to D6
Dim beginTIME As Double, trials As Long, i As Long, p As Long
trials = 1000000000
p = 0
beginTIME = Now
For i = 1 To trials
Call boomBYTE
Next i
Call Finished(p, Now - beginTIME, CDbl(trials))
p = p + 1
beginTIME = Now
For i = 1 To trials
Call boomINTEGER
Next i
Call Finished(p, Now - beginTIME, CDbl(trials))
p = p + 1
beginTIME = Now
For i = 1 To trials
Call boomLONG
Next i
Call Finished(p, Now - beginTIME, CDbl(trials))
p = p + 1
beginTIME = Now
For i = 1 To trials
Call boomDOUBLE
Next i
Call Finished(p, Now - beginTIME, CDbl(trials))
p = p + 1
beginTIME = Now
For i = 1 To trials
Call boomUNDECLARED
Next i
Call Finished(p, Now - beginTIME, CDbl(trials))
p = p + 1
End Sub
Private Sub boomBYTE()
Dim a As Byte, b As Byte, c As Byte
a = 1
b = 1 + a
c = 1 + b
c = c + 1
End Sub
Private Sub boomINTEGER()
Dim a As Integer, b As Integer, c As Integer
a = 1
b = 1 + a
c = 1 + b
c = c + 1
End Sub
Private Sub boomLONG()
Dim a As Long, b As Long, c As Long
a = 1
b = 1 + a
c = 1 + b
c = c + 1
End Sub
Private Sub boomDOUBLE()
Dim a As Double, b As Double, c As Double
a = 1
b = 1 + a
c = 1 + b
c = c + 1
End Sub
Private Sub boomUNDECLARED()
a = 1
b = 1 + a
c = 1 + b
c = c + 1
End Sub
Private Sub Finished(i As Long, timeUSED As Double, trials As Double)
With Range("B2").Offset(i, 0)
.Value = .Value + trials
.Offset(0, 1).Value = .Offset(0, 1).Value + timeUSED
.Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,0)"
End With
End Sub
Dim a as Variant, b as Variant, c As Variant
должен дать тот же результат, что и вовсе не "затемнение".
Это проблема space vs необходимость.
В некоторых ситуациях требуется необходимость использовать длинный. Если вы перебираете строки в большом файле excel, переменная, содержащая номер строки, должна быть длинной.
Однако иногда вы узнаете, что целое число может справиться с вашей проблемой, и использование длинной будет пустой тратой пространства (память). Отдельные переменные действительно не имеют большого значения, но когда вы начинаете разбираться с массивами, это может иметь большое значение.
В VBA7 целые числа составляют 2 байта, а longs - 4 байта.
Если у вас есть массив из 1 миллиона номеров между 1 и 10, использование массива Integer займет около 2 МБ ОЗУ, по сравнению с примерно 4 МБ ОЗУ для длинного массива.
Возможно, CS grad может объяснить это лучше, но да целому числу требуется меньше памяти для хранения (может быть, не очень важно в очень простом VBA script).
Он также гарантирует/подтверждает, что переменная всегда будет целочисленной (не десятичной). Я уверен, что если вы сохраните 6.7 как целое число, оно будет преобразовано в число 7 в VBA.
Возможно, это не лучшая практика, но могут быть случаи, когда это необходимо. Я считаю, что главная цель - проверка достоверности данных. В частности, да, для циклов, где что-то должно произойти Х количество раз - десятичное значение не имеет смысла.
Первичное различие - память, хотя - если я помню длинный бит 64 бит, а целое - 32 бит.