Подтвердить что ты не робот

Зачем использовать Integer вместо Long?

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

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

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

4b9b3361

Ответ 1

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

MSDN

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

MSDN

Таким образом, выгода заключается в уменьшении объема памяти. Integer занимает половину памяти, которую занимает long. Теперь мы говорим о 2 байтах, так что это не будет иметь большого значения, если вы не храните TON целых чисел.

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

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

Насколько я понимаю, основной движок VB преобразует целые числа в длинные, даже если он объявлен как целое число. Поэтому можно отметить небольшое снижение скорости. Я верил этому в течение некоторого времени, и, возможно, именно поэтому было сделано вышеупомянутое выражение, я не просил аргументации.

озгрид форумы

Это ссылка, которую я искал.

Короткий ответ: в 32-разрядных системах 2-байтовые целые числа преобразуются в 4-байтовые значения. На самом деле другого пути нет, поэтому соответствующие биты правильно выстраиваются для любой формы обработки. Рассмотрим следующее

MsgBox Hex(-1) = Hex(65535) ' = True

Очевидно, что -1 не равен 65535, но компьютер возвращает правильный ответ, а именно: "FFFF" = "FFFF"

Однако, если бы мы принудили -1 к длинному первому, мы получили бы правильный ответ (65535, превышающий 32 КБ, автоматически является длинным)

MsgBox Hex(-1&) = Hex(65535) ' = False

"FFFFFFFF" = "FFFF"

Как правило, в VBA нет смысла объявлять "как целое число" в современных системах, за исключением, возможно, некоторого устаревшего API, который ожидает получить целое число.

форум pcreview

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

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

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

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

Спасибо Vba4All за указание на это.

Ответ 2

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

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

целое число составляет 16 бит и может представлять значение между -32, 768 и 32,767

Длинный составляет 32 бита и может представлять -2, чтобы 2,147,483,647 147483648

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

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

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

Ответ 3

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

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

A Long имеет ширину 32 бита и (IMO) следует использовать там, где это возможно.

Ответ 4

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

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

РЕЗУЛЬТАТЫ НА ОКОНЧАТЕЛЬСТВЕ 64 БИТ WINDOWS 10

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

Ответ 5

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

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

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

  • В VBA7 целые числа составляют 2 байта, а longs - 4 байта.

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

Ответ 6

Я взял метод @PGSystemTester и обновил его, чтобы удалить потенциальную изменчивость. Помещая цикл в подпрограммы, это удаляет время, затрачиваемое на вызов подпрограммы (а это много времени). Я также отключил обновление экрана, чтобы устранить любые задержки, которые это может вызвать.

Long все еще работали лучше всего, и поскольку эти результаты более тесно ограничены воздействием только типов переменных, стоит отметить величину вариаций.

Мои результаты (рабочий стол, Windows 7, Excel 2010):

enter image description here

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

Option Explicit

Sub VariableOlympics()
'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
Dim chosenWorksheet As Worksheet

    Set chosenWorksheet = ThisWorkbook.Sheets("TimeTrialInfo")

    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
    Application.ScreenUpdating = False

    trials = 1000000000 ' 1,000,000,000 - not 10,000,000,000 as used by @PGSystemTester

    p = 0

    beginTIME = Now
    boomBYTE trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1

    beginTIME = Now
    boomINTEGER trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomLONG trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomDOUBLE trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1


    beginTIME = Now
    boomUNDECLARED trials
    Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2")
    p = p + 1

    Application.EnableEvents = True
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    chosenWorksheet.Calculate

End Sub


Private Sub boomBYTE(numTrials As Long)
Dim a As Byte, b As Byte, c As Byte

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomINTEGER(numTrials As Long)
Dim a As Integer, b As Integer, c As Integer

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomLONG(numTrials As Long)
Dim a As Long, b As Long, c As Long

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomDOUBLE(numTrials As Long)
Dim a As Double, b As Double, c As Double

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub


Private Sub boomUNDECLARED(numTrials As Long)
Dim a As Variant, b As Variant, c As Variant

Dim i As Long
For i = 1 To numTrials
    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1
Next i

End Sub

Private Sub Finished(i As Long, timeUSED As Double, trials As Double, initialCell As Range)

    With initialCell.Offset(i, 0)
            .Value = trials
            .Offset(0, 1).Value = timeUSED
            .Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,2)"
    End With

End Sub

Ответ 7

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

памятиУчитывая 1 миллион значений, разница между использованием целых и длинных будет составлять 2 байта для каждого значения, так что разница в 2 * 1 000 000/1024/1024 = меньше 2 МБ Ваша RAM, которая, вероятно, намного меньше, чем 1% или даже 0,1% от вашей оперативной памяти.

Обработка

Учитывая эталонный тест PGSystemTester, вы можете увидеть разницу в 811 - 745 = 66 секунд между Long и Integer при обработке 10 миллиардов пакетов по 4 операции в каждой. Уменьшите число операций до 1 миллиона операций, и мы можем ожидать, что разница во времени выполнения составит 66/10 000/4 = менее 2 мс.


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

Обратите внимание, что этот субъективный порог намного ниже верхнего предела Integer, я использую Longs просто для того, чтобы провести различие между моими собственными определениями малого и большого.

Ответ 8

Возможно, CS grad может объяснить это лучше, но да целому числу требуется меньше памяти для хранения (может быть, не очень важно в очень простом VBA script).

Он также гарантирует/подтверждает, что переменная всегда будет целочисленной (не десятичной). Я уверен, что если вы сохраните 6.7 как целое число, оно будет преобразовано в число 7 в VBA.

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

Первичное различие - память, хотя - если я помню длинный бит 64 бит, а целое - 32 бит.