Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1
RSS
Тип переменной Byte в цикле с отрицательным шагом вызывает ошибку
 
Обнаружил странность, которую не могу объяснить
Код
Sub DelSheets()
'Dim i As Long
Dim i As Byte
    With ThisWorkbook
        For i = .Sheets.Count To 2 Step -1
            .Sheets(i).Delete
        Next i
    End With
End Sub

Переменная типа Byte. В таком варианте  - ошибка Owerflow. Проверил, листов точно не больше 255 :)
При типе переменной Integer, Long переполнения нет.
 
У меня тоже выдаёт overflow

при long, при integer и при необъявлении работает нормально  
Изменено: Бахтиёр - 8 сен 2016 09:07:21
 
Наводка:
Код
Debug.Print TypeName(ThisWorkbook.Sheets.Count)
привести тип Byte к установленному для свойства Count типу не получится...

Ошибка. Сам тип можно привести. А вот сопоставить его с отрицательным шагом - нет. Т.к. тип Byte не может принимать значения меньше нуля...
Изменено: The_Prist - 8 сен 2016 09:13:30
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
The_Prist написал:  А вот сопоставить его с отрицательным шагом - нет.
Да, и такой код:
Код
Sub bbb()
Dim b As Byte
For b = 90 To 80 Step -1
MsgBox b
Next
End Sub
выдаёт Overflow.
Изменено: Бахтиёр - 8 сен 2016 09:33:06
 
Дима, да, тип Long. Но тут встречная пика: Long > Integer, но при этом с Integer ошибки нет. Значит, допустимо и Byte? (выяснили: допустимо)

Цитата
The_Prist написал: тип Byte не может принимать значения меньше нуля...
Вот оно. Спасибо.

Не впервые напоролся. Но забыл, что была шишка. Опять те же грабли...
 
Стоп... Не все понятно.
5 листов
Код
i = .Sheets.Count To 2 Step -1
- на первом, втором... шаге нуля нет. Да и на последнем нет.
Да, возможно, сопоставить Byte и отрицательный шаг нельзя, но почему причиной указано отрицательное число? Ведь переменная ниже 1 не уходит.
Код
Sub Ds()
Dim i As Byte
    i = 5
    i = i - 1
    MsgBox i
End Sub
 
Переменная не уходит, но VBA об этом не знает. Он предполагает, что такое может произойти, т.к. шаг отрицательный. Он определяется нижний и верхний порог цикла отдельно от шага, так скажем.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
vikttur, я только предположу. Логично, если счётчик типа байт, то и шаг типа байт, а байт не может быть меньше ноля. :)

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
Виктор, добрый день. Да, там отладчик пугается минуса в операторе цикла с типом Byte на стадии, когда он еще не оценивает, станет ли оператор в итоге отрицательным.
Может, лучше сэкономим на времени исполнения, чем на байтах ? :)
Код
Sub Test()
  Dim a(), i ' As Byte
  With ThisWorkbook
    ReDim a(2 To .Sheets.Count)
    For i = 2 To .Sheets.Count
      a(i) = i
    Next
    Application.DisplayAlerts = False
    ' Удалить сразу все листы, перечисленные в массиве a()
    .Sheets(a).Delete
    Application.DisplayAlerts = True
  End With
End Sub
Изменено: ZVI - 8 сен 2016 09:36:49
 
Цитата
JayBhagavan написал: Логично, если счётчик типа байт, то и шаг типа байт, а байт не может быть меньше ноля.
+1 ИМХО
 
Цитата
The_Prist написал: определяется нижний и верхний порог цикла отдельно от шага
Цитата
JayBhagavan написал:  если счётчик типа байт, то и шаг типа байт
Цитата
ZVI написал: отладчик пугается минуса в операторе цикла с типом Byte на стадии, когда он еще не оценивает, станет ли оператор в итоге отрицательным.
Не подумал, что он такой перепуганный )
Спасибо всем.
 
Цитата
ZVI написал: сэкономим на времени исполнения, чем на байтах
Я не удаляю пачками по сотне штук )
За пример спасибо.
 
Скажите, а какой тайный смысл объявлять указатель счетчика цикла типом Byte?
Чем шире угол зрения, тем он тупее.
 
ИМХО всё дело как писал JayBhagavan, в шаге.
Потому что такой код:
Код
Sub ggg()
Dim i As Integer
For i = 7 To 8 Step 30000
MsgBox i
Next
End Sub
выдаёт 7

А вот такой код:
Код
Sub ggg()
Dim i As Integer
For i = 7 To 8 Step 40000
MsgBox i
Next
End Sub
сразу выдаёт Overflow, (не выдавая 7)

То есть счётчик типа Integer, логично - шаг тоже типа Integer.
1-й код работает нормально - ибо, 30 000 подпадает под Integer.
2-й код выдаёт ошибку - ибо, 40 000 НЕ подпадает под Integer.
Изменено: Бахтиёр - 8 сен 2016 10:07:04
 
Цитата
SAS888 написал: Скажите, а какой тайный смысл объявлять указатель счетчика цикла типом Byte?
экономия ресурсов/памяти
 
Да, там зверская экономия - целый байт :)
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Обнаружил еще одну интересную вещь. В следующем коде
Код
Sub qq()
    Dim i As Integer
    For i = 1 To 9 Step 1.5
        MsgBox i
    Next
End Sub
тип данных переменной и шага не совпадают. Ошибки переполнения, естественно, нет, а переменная i просто округляется до значения своего типа (до целых).
Чем шире угол зрения, тем он тупее.
 
SAS888, нормальная ситуация, т.к.:
Код
? cint(40000)
выдаст ошибку переполнения, а:
Код
? cint(1.5)
выдаст 2. :)

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
Никакой экономии памяти (кроме как на тексте программы: byte - 4 символа, Integer - 7) по факту нет, переменные в памяти выравниваются по четным адресам (помнится ещё со времен DOS`а).
А вот на производительности использование Byte может сказаться в худшую сторону - процессоры у большинства из нас уже не восьми (и даже не 16-и) разрядные...
 
Цитата
Апострофф написал:
А вот на производительности использование Byte может сказаться
Ага. Поэтому лучше всего вообще Long использовать - он наиболее подходит под современные архитектуры.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
В задачи отладчика не входит анализ "высокоуровневых" намерений программиста, для определенных ситуаций делается лишь упрощенная оценка возможности переполнения. В частности. отладчик перестраховывается при операторе цикла с типом Byte и отрицательном шаге, так как в определенных ситуациях это может привести к переполнению типа. В общем, не очеловечивайте отладчик VBA, он этого не любит :)
Код
Sub Test()
  
  Dim i ' As Long
  
  ' Собственно, вот такая ситуация по выходу из цикла переполнила бы тип Byte,
  ' потому что For Next в конце делает лишний шаг для i
  For i = 1 To 0 Step -1
  Next
  Debug.Print i ' равно -1
  
  ' А это просто демонстрация того, что не рекомендуется внутри цикла менять значение переменой цикла
  For i = 3 To 2 Step -1
    i = 2 = 2
  Next
  Debug.Print i ' равно -2

End Sub
 
Цитата
JayBhagavan написал: cint(1.5)выдаст 2.
И я про это. VB автоматом делает CInt(). Т. е. компилятору "фиолетово" каким типом задан шаг. При интерпретации он его "подгоняет" под тип переменной указателя. И, если не получается (например, переполнение), то будет ошибка. Т. е. тип шага НЕ ОБЯЗАТЕЛЬНО должен совпадать с типом переменной.
Чем шире угол зрения, тем он тупее.
 
Цитата
The_Prist написал: Поэтому лучше всего вообще Long использовать
Так и использую. А Byte остался в старых файлах. Копался и напоролся.
 
Цитата
SAS888 написал: Т. е. тип шага НЕ ОБЯЗАТЕЛЬНО должен совпадать с типом переменной.
Да, но ОБЯЗАТЕЛЬНО чтобы было возможно шаг привести в типу счётчика.

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
Цитата
забыл, что была шишка. Опять те же грабли...
народная мудрость гласит, что больнее всего наступать на детские грабли!
Изменено: Ігор Гончаренко - 8 сен 2016 12:58:32
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
Страницы: 1
Читают тему (гостей: 1)
Наверх