Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/121: Рейтинг темы: голосов - 121, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 16.06.2015
Сообщений: 1

Чтение и изменение бита в числе

16.06.2015, 12:30. Показов 24405. Ответов 35
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Столкнулся с такой проблемой - через СOM порт от контроллера получаю массив байт данных, сохраняю их в виде переменной Double.
Visual Basic
1
2
3
4
5
6
Case Is = 2         
        intInf(0) = Asc(MSComm1.Input) '
        intInf(1) = Asc(MSComm1.Input) ' 
        intInf(2) = Asc(MSComm1.Input) ' 
        intInf(3) = Asc(MSComm1.Input) ' 
       ' и т.д

Каждый установленный бит в числе имеет смысловую нагрузку. Вопрос -каким образом можно обращаться к отдельным битам в числе (Аналог команды в ассемблере setb Acc.N (установить бит N в "1") и clr Acc.N (установить бит N в "0")). Пока что додумался только до преобразования полученного числа в бинарный вид при помощи функции

Visual Basic
1
2
3
4
5
6
7
8
9
10
Public Function ToBin(ByVal bByte As Byte) As String
Dim i As Integer
For i = 0 To 7
If bByte And 2 ^ i Then
ToBin = 1 & ToBin
 Else
ToBin = 0 & ToBin
 End If
Next i
End Function
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.06.2015, 12:30
Ответы с готовыми решениями:

Операция "сброса бита в числе" (число и номер бита)
Как в калькуляторе сделать сброс бита в числе (число и номер бита)? В сети, нашел только это: #### value=(sbyte) value &...

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

Установка бита в двоичном числе
Добрый день! Столкнулся с проблемой при установке бита в двоичном числе. использую функцию bts, однако при запуске выдает следующую ошибку:...

35
Заблокирован
16.06.2015, 12:40
Цитата Сообщение от Forgot Посмотреть сообщение
сохраняю их в виде переменной Double
И где в вашем коде хоть одно упоминание про Double?

Добавлено через 2 минуты
bByte and 1 - нулевой бит
bByte and 2 - первый бит
bByte and 4 - второй бит
bByte and 8 - третий бит
и т.д.
0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
16.06.2015, 14:20
Лучший ответ Сообщение было отмечено The trick как решение

Решение

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Private Sub Form_Load()
    Dim b As Long
    Dim index As Long
    ' Работаем с 3-м битом (индексация от 0)
    index = 3
    ' Установить бит
    b = b Or (2 ^ index)
    ' Сбросить бит
    b = b And Not (2 ^ index)
    ' Инвертировать бит
    b = b Xor (2 ^ index)
    
End Sub
Но правильнее задать массив масок т.к. оператор '^' вещественный, и это сильно замедляет вычисление и не позволяет работать с 32 битом.
3
16.06.2015, 17:17

Не по теме:

Цитата Сообщение от The trick Посмотреть сообщение
оператор '^' вещественный
Лучше сдвиг использовать.

0
Модератор
10057 / 3902 / 884
Регистрация: 22.02.2013
Сообщений: 5,853
Записей в блоге: 79
16.06.2015, 17:25
Цитата Сообщение от locm Посмотреть сообщение
Лучше сдвиг использовать.
В VB6 нет сдвигов только умножения, но для получения значения умножения для сдвига нужно либо возводить в степень либо иметь массив заранее подготовленных значений. Но тогда уж лучше иметь массив масок, как я сказал ранее - это еще быстрее.
2
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
10.11.2017, 04:05
Идеалом было бы иметь массив констант = константа-масcив.

Если это нельзя, то надо просто вычислить, вернее, задать вручную элементы массива.
Что-то вроде
Visual Basic
1
2
3
4
5
6
Dim Deg2(0 to 15) as long
Deg2(0) =1
Deg2(1) =2
Deg2(2) =4
.....
Deg2(15)=32768

Битовые операторы в VBA такие же, как в Паскале:
Or, And, Xor


Теперь, чтобы узнать, выставлен ли пятый бит в маске М, пишем
Visual Basic
1
2
Dim Bit5Exist as Boolean
Bit5Exist = M And Deg2(5)
это умножение.
Строго говоря, результат операции не Boolean, а Long, причем в случае отсутствия бита имеем 0, а случае присутствия имеем 32. Но VBA преобразует 0 в False, а 32 в True

Чтобы выставить пятый бит пишем:
Visual Basic
1
M = M Or Deg2(5)
это сложение

Чтобы перекинуть (изменить) пятый бит пишем:
Visual Basic
1
M = M Xor Deg2(5)
это вычитание

Чтобы скинуть (обнулить) пятый бит надо применить двойную операцию:
Visual Basic
1
M = (M Or Deg2(5)) Xor Deg2(5)
В последнем случае мы сначала гарантировано выставляем пятый бит, а затем делаем перекидывание, гарантированно обнуляющее пяты бит. Т.е. сначала сложение

В принципе можно и так:

Visual Basic
1
M = M And (Deg2(15)-Deg2(5)-1)
но первый способ представляется более естественным
0
Заблокирован
10.11.2017, 23:59
Цитата Сообщение от MU-GK Посмотреть сообщение
Чтобы скинуть (обнулить) пятый бит надо применить
Цитата Сообщение от The trick Посмотреть сообщение
b = b And Not Deg2(5)
, не применяя "двойных операций" и прочих лисопедов.
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
11.11.2017, 01:31
Верно!
Про Not я и забыл совсем!
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
25.11.2017, 15:19
В итоге вот такой маленький код:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Public Deg2 as Variant
Sub InitDeg2()
 Deg2 = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)
End Sub
Function BitGet(m, N As Byte) As Boolean
 BitGet = m And Deg2(N)
End Function
Function BitPut(m, N As Byte) As Long
 BitPut = m Or Deg2(N)
End Function
Function BitOut(m, N As Byte) As Long
 BitOut = m And Not Deg2(N)
End Function
Function BitSwp(m, N As Byte) As Long
 BitPut = m Xor Deg2(N)
End Function
Добавлено через 3 минуты
Функции BitXxx(m, N as byte) как раз и производят описанные выше операции:
BitGet - Показывает бит
BitPut - Выставляет бит
BitOut - Сбрасывает бит
BitSwp - Перекидывает бит
2
oh my god
 Аватар для fever brain
1456 / 796 / 161
Регистрация: 05.01.2016
Сообщений: 2,307
Записей в блоге: 8
25.11.2017, 17:46
Я про это знал давно, но решил пойти дальше, и даже продемонстрировать ну очень наглядно
если жать на CheckBox'ы то число будет всевремя меняться
используется только Xor

Для работы этого кода нужно только скопировать код в модуль формы

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Option Explicit
'
'Хороший пример для демонстрации битовой операции Xor
'Объеденил с CheckBox
'
Const Dig = 16 'Число разрядов можно изменить
Const r = 90, rr = r * 2
Dim WithEvents ch As CheckBox, WithEvents tx As TextBox, WithEvents bt As CommandButton
 
Private Sub ch_Click()
    tx.Text = Val(tx.Text) Xor d(Mid$(ch.Name, 3))
End Sub
 
Public Property Get d()
    Static i&, dd&(): Do Until i: ReDim dd(Dig + 1): For i = 0 To Dig: dd(i + 1) = 2 ^ i: Next: Exit Do: Loop: d = dd
End Property
 
Private Sub NewFocus()
    On Error Resume Next: Set ch = ActiveControl: Set tx = ActiveControl: Set bt = ActiveControl
End Sub
 
Private Sub bt_Click()
    Dim i&: For i = 1 To Dig: Controls("ch" & i).Value = 0: Next: tx.Text = 0
End Sub
 
Private Sub Form_Load()
    Dim i&, l&, lb As Label
    Me.Caption = "Xor"
    For i = 1 To Dig
        Set ch = Controls.Add("vb.CheckBox", "ch" & Dig - i + 1): With ch
            .Move l + r, r, rr, rr: l = l + rr: .Visible = 1
        End With
    Next
    Set tx = Controls.Add("vb.TextBox", "tx"): With tx
        .Move r, rr * 2, rr * 8, r * 3: .Visible = 1
    End With
    Set bt = Controls.Add("vb.CommandButton", "bt"): With bt
        .Move tx.Width + r, rr * 2, rr * 8, r * 3: .Caption = "Сброс": .Visible = 1
    End With: bt_Click
End Sub
 
Private Sub Form_Activate(): NewFocus: End Sub
Private Sub ch_LostFocus(): NewFocus: End Sub
Private Sub tx_LostFocus(): NewFocus: End Sub
Private Sub bt_LostFocus(): NewFocus: End Sub
Миниатюры
Чтение и изменение бита в числе  
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
26.11.2017, 02:08
Выше описано 16-разрядная версия.
Возможно, кому-то покажется интересной 32-разрядная

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Public Deg2(0 To 31) As Long
Sub InitDeg2()
 Dim p As Long
 
 Deg2(0) = 1
 For p = 1 To 30
  Deg2(p) = 2 * Deg2(p - 1)
 Next p
 Deg2(31) = -2 * Deg2(30)
 
End Sub
1
 Аватар для Sur_L
103 / 63 / 10
Регистрация: 13.02.2017
Сообщений: 178
30.11.2017, 18:06
Так как быть с 32-м битом?
С числом FFFFFFFF выдаст оверфлор...
0
oh my god
 Аватар для fever brain
1456 / 796 / 161
Регистрация: 05.01.2016
Сообщений: 2,307
Записей в блоге: 8
30.11.2017, 18:23
Цитата Сообщение от Sur_L Посмотреть сообщение
Так как быть с 32-м битом?
32-й бит в Long задействован под флаг положительного/отрицательного числа
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
30.11.2017, 18:24
Никак не быть.
В типе Long нет бита #32.
Последний бит #31.
Т.е. их всего 32, но нумеруются они с нуля, так что 32-ой бит имеет #31
0
oh my god
 Аватар для fever brain
1456 / 796 / 161
Регистрация: 05.01.2016
Сообщений: 2,307
Записей в блоге: 8
30.11.2017, 18:30
Это у тебя пальцев всего девять, потомучто нумеруются с нуля !
32 бита использует бейсик для своих операций арифметических/логических
от -2147483647 и до 2147483647 всего будет 2 ^32
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
30.11.2017, 18:45
Битов 32, а вот номер у 32-го как раз 31.
Если Вас интересует, что надо писать в последний бит, так в описании инициализации массива Deg2 это показано:
Deg2(31) = - 2^31

Т.е. так:
Deg2(k) =+ 2^k при k<31
Deg2(k) =- 2^k при k= 31
0
 Аватар для Sur_L
103 / 63 / 10
Регистрация: 13.02.2017
Сообщений: 178
30.11.2017, 19:06
Все всё поняли, вопрос был есть ли способ таки узнать старший бит у unsigned long числа (которого нет в вб6)...
Чисто есть, а действий с ним производить нельзя...
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
30.11.2017, 19:20
Могу предположить, что узнать это можно простым сравнением.
Для простого Long это будет:

m < 0

Для UnSigned Long, он же, наверное, LongWord вот так:

m > SummDeg2(30)

Где SummDeg2(N) функция, возвращающая сумму степеней двойки до N включительно

Visual Basic
1
2
3
4
5
6
7
8
9
Function SummDeg2(ByVal N) as Long
 Dim k As Long, SD2 as Long, D2 as long
 D2 = 1
 SD2 = D2
 for k = 1 to N
  D2 = 2*D2
  SD2 = SD2 + D2
 Next k
End Function
1
 Аватар для Sur_L
103 / 63 / 10
Регистрация: 13.02.2017
Сообщений: 178
01.12.2017, 16:23
Состыковал в кучку
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Private Deg2(0 To 31) As Long
 
Private Sub Command1_Click()
Dim m As Double, i As Long
 
'm = &HFFFFFFFF
m = 2863311530#
'm = 1431655765
'm = &HF0F0F0F0
 
Call InitDeg2
 
For i = 31 To 0 Step -1
    Debug.Print CStr(getBitULong(m, i));
Next i
Debug.Print
 
End Sub
 
Function getBitULong(L As Double, n As Long) As Long
Dim sd30 As Long
 
sd30 = SummDeg2(30)
 
If n = 31 Then
    If L > sd30 Or L < 0 Then
        getBitULong = 1
        Exit Function
    End If
Else
    If L > sd30 Then L = L - sd30 - 1
    If (L And Deg2(n)) <> 0 Then getBitULong = 1
End If
 
End Function
 
Sub InitDeg2()
Dim p As Long
 
Deg2(0) = 1
For p = 1 To 30
    Deg2(p) = 2 * Deg2(p - 1)
Next p
 
End Sub
 
Function SummDeg2(ByVal n) As Long
Dim k As Long, D2 As Long
D2 = 1
SummDeg2 = 1
For k = 1 To n
    D2 = 2 * D2
    SummDeg2 = SummDeg2 + D2
Next k
End Function
0
34 / 31 / 1
Регистрация: 06.01.2017
Сообщений: 300
02.12.2017, 15:19
Рекомендую прописать ByVal для аргумента L.

Иначе VBA будет ворчать каждый раз, когда ты будешь в качестве L использовать не Double, так что придётся аргумент заключать в скобки.
А с ByVal переменная любого (числового!!!) типа будет интерпретироваться как Double.
Т.е. вот так:
Visual Basic
1
Function getBitULong(byVal L As Double, n As Long) As Long
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.12.2017, 15:19
Помогаю со студенческими работами здесь

Инвертирование определенного бита в заданном числе
Напишите программу, которая инвертирует определенный бит в заданном числе (биты при этом нумеруются с 0, начиная с младших).

Побитовыми операциями поменять местами в числе по 2 бита
Задали побитовыми операциями поменять местами в числе по 2 бита то есть в веденном числе последние два бита в начало за ними...

Ошибка при определении нужного бита в большем числе
Здравствуйте, столкнулся с такой проблемой. Я не могу определить какой бит у меня находится в определенной позиции в числе...

Найти номер первого (последнего) справа нулевого бита в целом числе a
Найти номер первого (последнего) справа нулевого бита в целом числе a.

Чтение бита четности
Здравствуйте. У меня есть вопрос: Как считать бит четности через с++? Написана программа которая будет общаться с устройством через...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru