Почему использовать целое вместо длинного

vba integer long-integer integer-overflow


Я часто вижу вопросы, связанные с ошибками Overflow с помощью VBA .

Мой вопрос, почему использовать integer объявление переменной , вместо того , чтобы просто определить все числовые переменные ( за исключением double и т.д.) , как long ?

Если вы не выполняете операцию, подобную циклу for, где вы можете гарантировать, что значение не превысит ограничение в 32 767, это повлияет на производительность или что-то еще, что будет диктовать отсутствие использования long ?




Answer 1 RubberDuck


Целочисленные переменные хранятся в виде 16-битных (2-байтовых)чисел

Office VBA Ссылка

Длинные (длинные целые)переменные хранятся в виде подписанных 32-битных (4-байтовых)чисел

Office VBA Ссылка

Итак,преимущество в уменьшенном объеме памяти.Интегральное целое занимает половину памяти,чем длинное.Сейчас мы говорим о 2 байтах,поэтому для отдельных целых чисел это не будет иметь реального значения,это касается только TONS целых чисел (например,больших массивов),и использование памяти является критичным.

НО в 32- битной системе использование памяти в два раза сокращается за счет производительности. Когда процессор фактически выполняет некоторые вычисления с 16-битным целым числом (например, увеличивает счетчик цикла), значение молча преобразуется во временный Long без использования большего диапазона чисел для работы. Переполнения по-прежнему происходят, и регистр, который процессор использует для хранения значений для расчета, будет занимать одинаковое количество памяти (32 бита) в любом случае. Производительность может даже ухудшиться, потому что тип данных должен быть преобразован (на очень низком уровне).

Не та ссылка,которую я искал,но....

Насколько я понимаю,лежащий в основе движок 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,которые ожидают получения Целого.

форум pcreview

И наконец я нашел документацию MSDN, которую я действительно искал.

Традиционно,программисты VBA использовали целые числа для хранения малых чисел,так как они требовали меньше памяти.Однако в последних версиях VBA преобразует все целочисленные значения в тип Long,даже если они объявлены как тип Integer.Таким образом,преимущества в производительности при использовании целочисленных переменных больше нет;на самом деле,переменные типа Long могут быть немного быстрее,так как VBA не нужно их преобразовывать.

Поясним, основываясь на комментариях: целым числам по- прежнему требуется меньше памяти для хранения - большому массиву целых потребуется значительно меньше оперативной памяти, чем массиву Long с такими же размерами Но поскольку процессор должен работать с 32-разрядными порциями памяти, VBA временно преобразует целые числа в длинные, когда выполняет вычисления


Итак, в итоге, почти нет веских причин использовать тип Integer в наши дни. Если вам не нужно взаимодействовать со старым вызовом API, который ожидает 16-битное целое число, или если вы работаете с большими массивами маленьких целых чисел и память стоит дорого.

Стоит отметить,что некоторые старые функции API могут ожидать параметры,которые являются 16-битными (2-байтными)Целочислениями,и если вы находитесь на 32 битах и пытаетесь по ссылке передать Целое (то есть уже 4-байтовую длину),то это не будет работать из-за разницы в длине байтов.

Спасибо Vba4All за то,что указал на это.




Answer 2 Patrick


Как отмечалось в других ответах,реальная разница между int и long заключается в размере его объема памяти и,следовательно,в размере числа,которое он может держать.

вот полная документация по этим типам данных: http://msdn.microsoft.com/en-us/library/office/ms474284(v=office.14).aspx

Целое число составляет 16 бит и может представлять собой значение в диапазоне от 32768 до 32767

Long 32 бита и может представлять -2147483648 до 2147483647

и есть LongLong, который составляет 64 бита и может обрабатывать как 9 Pentilion

Один из самых важных моментов,который следует помнить при этом,это то,что типы данных различаются и языком,и операционной системой/платформой.В вашем мире VBA длина составляет 32 бита,а в c#на 64-битном процессоре длина составляет 64 бита.Это может внести существенную путаницу.

Хотя VBA не поддерживает его, при переходе на любой другой язык в .net, java или другом я очень предпочитаю использовать системные типы данных int16 , int32 и int64, что позволяет мне гораздо более прозрачно понимать значения, которые может быть проведен в этих типах данных.




Answer 3 Alex K.


У VBA много исторического багажа.

Integer имеет ширину 16 бита и был хорошее значение по умолчанию числового типа назад , когда размеры 16 битной архитектуры / слова были распространены.

Long составляет 32 бит и (ИМО) должен использоваться везде , где это возможно.




Answer 4 PGSystemTester


Хотя этому посту уже четыре года, мне было любопытно, и я провел несколько тестов. Самое важное, на что следует обратить внимание, это то, что кодировщик ВСЕГДА должен объявлять переменную как SOMETHING . Необъявленные переменные явно показали худшее (необъявленные являются технически Variant )

Long действовал быстрее всех, поэтому я думаю, что рекомендация Microsoft всегда использовать Long вместо Integer имеет смысл. Я предполагаю то же самое, что и в случае с Byte , но большинство кодеров не используют это.

РЕЗУЛЬТАТЫ НА 64 BIT WINDOWS 10 LAPTOP

Variable Olympics

Используемый код:

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



Answer 5 Alter


Это проблема пространства и необходимости .

В некоторых ситуациях необходимо использовать длинные. Если вы просматриваете строки в большом файле Excel, переменная, которая содержит номер строки, должна быть длинной.

Тем не менее, иногда вы будете знать, что целое число может решить вашу проблему, и использование long будет пустой тратой пространства (памяти). Отдельные переменные на самом деле не имеют большого значения, но когда вы начинаете работать с массивами, это может иметь большое значение.

  • В VBA7 интегралы составляют 2 байта,а длина-4 байта.

  • Если у вас есть массив из 1 миллиона чисел от 1 до 10, использование массива Integer займет около 2 МБ ОЗУ, по сравнению с примерно 4 МБ ОЗУ для длинного массива.