LINUX.ORG.RU
решено ФорумTalks

булевая логика

 ,


0

1

приветствую!

Как правильно проверить наличие флагов?
нужно проверить на совпадение одного или нескольких флагов, к примеру 10, может включать 10 или 8 или 2.
но если уже 11, то проверяем на 10, 8, 2 и единичка лишняя
проверка не прошла

прочитал више и мало что понял, но сложно обяснить, поэтому пример:

ОБНОВЛЕН

01010 | 01010 | pass      
01000 | 01010 | pass       
00010 | 01010 | pass
00100 | 01010 | not valid
01011 | 01010 | not valid
00000 | 01010 | not valid
11010 | 01010 | not valid




★★★★

Последнее исправление: kiotoze (всего исправлений: 2)

(val || mask) == mask ступил, на 0 надо ещё проверить

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 3)

https://tproger.ru/articles/awesome-bits/

Но вообще моветон такое делать. ТС, а как у тебя сам флаг организован? Каждая цифра отвечает за какое-то независимое состояние и тебе грубо говоря надо проверять состояние некоторых разрядов в двоичной записи или там что-то более хитрое и тебе надо проверять заданные комбинации?

peregrine ★★★★★
()

если я правильно понял табличку, то сначала ИЛИ по валидным флагам, если на выходе 1, то ИЛИ по невалидным, если 0, то ок

vaddd ★☆
()
Ответ на: комментарий от Siborgium

Мы о разном. Я не про ИЛИ с маской из единиц, а про ИЛИ валидных/невалидных бит с маской из нулей )

vaddd ★☆
()

Почему это тру 01010 | 00010 | pass

а это уже не тру?11010 | 01010 | not valid

У тебя условия задачи противоречивые.

BceM_IIpuBeT ★★☆☆☆
()
Последнее исправление: BceM_IIpuBeT (всего исправлений: 1)
Ответ на: комментарий от vaddd

Ну, если поменять, то тогда мой ответ подходит:

val >= mask && val & mask
sudopacman ★★★★★
()
Ответ на: комментарий от peregrine

есть значение, куда набиваются флаги
11010

к примеру
1000 status1
0010 status2
10000 error

и такой результат возвращает функция 11010
мне нужно проверять, есть ли в наборе status1 или status2 или они оба
если нет ни одного из status1, status2 - значит ошибка
но если в наборе есть что-то еще кроме status1, status2 - значит ошибка и неважно какая

kiotoze ★★★★
() автор топика
Ответ на: комментарий от kiotoze

А почему тогда

11010 | 01010 | not valid

В наборе - статусы и ничего кроме них.

pinus_nigra
()
Ответ на: комментарий от kiotoze

01010 содержит 01000, что не входит в 00010. Почему там pass?

sudopacman ★★★★★
()
Ответ на: комментарий от kiotoze

Если статусы фиксированные и надо только их смотреть, без выделения отдельного смысла, то я бы как-то так делал:

enum States{
    State1 = 0x0001,
    State2 = 0x0010,
    State3 = 0x0101
};
if (value == State2){
//какой-то там код
}
И не выносил себе мозги булевой логикой. Ну и проверку делал бы есть в enum-е это или нету. А как это от ЯП зависит. В C++, например, можно так. Ну или я не понял что ты там хочешь делать

ЗЫ

Вроде понял что ты хочешь глядя на другие комментарии, тебе надо проверить корректность по маске, сейчас напишу лучше.

Первая колонка это состояние, а вторая - маска? Или опять неверно?

ЗЫ

Таблицу истинности напиши, я не понимаю что у тебя в данных, они противоречивые

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 4)
Ответ на: комментарий от kiotoze

Погоди, не понял. Тебе достаточно проверять что второе число меньше первого что-ли? Или я ННП

peregrine ★★★★★
()

что такое
«нужно проверить на совпадение одного или нескольких флагов»
совпадение с чем флагов вообще?

xmikex ★★★★
()
Ответ на: комментарий от kiotoze

У вас в слове есть две группы битов - биты статуса и биты ошибки. Для pass нужно чтобы хотя бы один бит статуса был «1» и не было ни одного бита ошибки в «1». Так? Если нет - попробуйте объяснить словами. Если да , то вам уже предложили кучу способов

vaddd ★☆
()
Ответ на: комментарий от peregrine

обновил пример
грубо говоря колонки местами нужно поменять
истинно когда:
- хоть один флаг совпал
- нет лишних флагов установленно

вижу что намудрено
я уже от булевой отказался, но итересно как с булевой решить)

kiotoze ★★★★
() автор топика
Ответ на: комментарий от kiotoze

А так:

res = 
(
      (data & flag) /* есть пересечения */
      && /* и */
      (
        !(data ^ flag) /* полное совпадение (xor == 0) */
        || /* или */
        ((data ^ flag) & flag) /* бит выпал из флага, а не из данных */
       )
)

#include <stdio.h>

int main()
{
    unsigned char d[] = {0b01010,0b01000,0b00010,0b00100,0b01011,0b00000,0b11010};
    unsigned char f[] = {0b01010,0b01010,0b01010,0b01010,0b01010,0b01010,0b01010};
    for(int i = 0; i < 7; i++)
    {
	printf("res: %d\n", (d[i] & f[i]) && (!(d[i] ^ f[i]) || (d[i] ^ f[i]) & f[i]));
    }
return 0;
}

? )

Toxo2 ★★★★
()
Ответ на: комментарий от kiotoze

булевая логика (комментарий)

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

0|0|+
0|1|-
1|0|+
1|1|+
+ кодируем как единичку, понимаем что это - обратная импликация, которая записывается как A∨(¬B). Дальше я воспользуюсь питоном, он мне ближе и роднее

файл mask.py

def check_mask(mask, value):
    if int(mask, 2) == 0:
        print('not valid')
        return False
    if int(int(value, 2) | (~ int(mask, 2))) == -1:
        print('pass')
        return True
    else:
        print('not valid')
        return False


if __name__ == '__main__':
    check_mask('0b01010', '0b01010')
Файл maskTest.py
import unittest
from mask import *


class TestMask(unittest.TestCase):
    def test_check_mask(self):
        actual = check_mask('0b01010', '0b01010')
        expected = True
        self.assertEqual(actual, expected)
        actual = check_mask('0b01000', '0b01010')
        expected = True
        self.assertEqual(actual, expected)
        actual = check_mask('0b00010', '0b01010')
        expected = True
        self.assertEqual(actual, expected)
        actual = check_mask('0b00100', '0b01010')
        expected = False
        self.assertEqual(actual, expected)
        actual = check_mask('0b01011', '0b01010')
        expected = False
        self.assertEqual(actual, expected)
        actual = check_mask('0b00000', '0b01010')
        expected = False
        self.assertEqual(actual, expected)
        actual = check_mask('0b11010', '0b01010')
        expected = False
        self.assertEqual(actual, expected)


if __name__ == "__main__":
    unittest.main()
Всё работает. Получилось правда через попу, т.к. я начал код писать до правки тобой сообщения, потом меня отвлекли, я ушел ужинать, кота кормить, а тут всё наоборот стало, но мне уже было лень переделывать. На -1 проверяем из-за того что питон первый бит числа инверсит тоже, который за знак отвечает.

peregrine ★★★★★
()

(a != 0) && (a & b == a)

И во-первых, булева, а не «булевая», во-вторых, это не булева логика, а битовые операции.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от vaddd

мда, что-то долго вы обсуждаете

mask | flags

должно вернуть маску, если что-то другое, то в флагах что-то другое

блин, сам кучу исправлений сделал, а в итогде вообще одна операция над битами, ну или можно как в предыдущем варианте получить синдром.

и опять наврал, синдром через «или не»

зы: кофейку надо, не проснулся и порядок действий

(mask | flags) ^ mask

Morin ★★★★★
()
Последнее исправление: Morin (всего исправлений: 5)
Ответ на: комментарий от peregrine

Идея правильная, а код не рабочий.

«абаснуй». только без придирок к синтаксису - писал с телефона на бегу, олимпиада же.

yax123 ★★★★★
()
Последнее исправление: yax123 (всего исправлений: 1)
Ответ на: комментарий от Morin

работает
мне кажется, что так даже понятней чем через ~ делатьа
спасибо!

kiotoze ★★★★
() автор топика

огромное спасибо за помощь!

kiotoze ★★★★
() автор топика
Ответ на: комментарий от yax123

Тоже сначала так же написал как и у тебя, но заваливаются тесты вот на этом кусочке:

Else if(val & (~mask))

; // Not valid

Else ; // valid

А вот так все проходят

Else if(val & (~mask))

; // valid

Else ; // Not valid

Хотя, возможно ТС-а обновления это поменяли. Ну или я не помню к чему if приводится в C

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

инверсия при разборе флагов плохая практика, можно знатно стрельнуть в ногу со знаковыми беззнаковыми

Morin ★★★★★
()
Ответ на: комментарий от peregrine

Если статусы фиксированные и надо только их смотреть, без выделения отдельного смысла, то я бы как-то так делал:

Ты там hexadecimal с binary не попутал, не? :)

В C++, например, можно так

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

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Ответ на: комментарий от slackwarrior

Ты там hexadecimal с binary не попутал, не? :)

наверное попутал, давно c++ не юзал

peregrine ★★★★★
()

Значениями битовых флагов должны быть двойки в степени иначе работать не будет. Там все на двоичное представление завязано. Должны быть 0001, 0010, 0100. Сочетания этих флагов будут давать что-то типа 0101.

In [11]: (2 | 4 | 8) & 8
Out[11]: 8

In [12]: (2 | 4) & 8
Out[12]: 0

...

In [16]: CREATE = 1 << 1

In [17]: READ = 1 << 2

In [18]: UPDATE = 1 << 3

In [19]: DELETE = 1 << 4

In [20]: CREATE
Out[20]: 2

In [21]: DELETE
Out[21]: 16

In [22]: CREATE | READ | UPDATE
Out[22]: 14

In [23]: (CREATE | READ | UPDATE) & DELETE
Out[23]: 0

In [24]: (CREATE | READ | UPDATE) & UPDATE
Out[24]: 8

tz4678 ★★
()
Последнее исправление: tz4678 (всего исправлений: 1)
Ответ на: комментарий от peregrine
        actual = check_mask('0b01010', '0b01010')
        expected = True
        self.assertEqual(actual, expected)
        actual = check_mask('0b01000', '0b01010')
        expected = True
...

Кто вас заставляет так писать? Почему нельзя сделать

     // a         b         result
      ['0b01010','0b01010', True   ],
      ['0b01000','0b01010', True   ],
...
А потом прогнать эту структуру в каком-нибудь цикле?

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от cobold

То что в первых двух колонках в первом посте.

slovazap ★★★★★
()

Не специально, чисто логикой, прогу лень было писать...

01010 | 01010 | pass      
01000 | 01010 | pass       
00010 | 01010 | pass
00100 | 01010 | not valid
01011 | 01010 | not valid
00000 | 01010 | not valid
11010 | 01010 | not valid

01010   01010
010-0   01010
0-010   01010

0-0-0   01010   pass

Вместо минусов вставить 1, но только один раз, либо в первыйминус, либо во второй. Остальное ноль. Хорошая разминка для логики, спасибо.

ЗЫ: Хотя, чувствовал же какой-то подвох, не зря же второе выражение было, двоичные операции? Ну я так не помню, надо все перебрать, а мне попросту лень лезть в справочник по ассемблеру. В последний раз я писал на нём 20 лет назад. Даже могу сказать что, загрузчик в MBR. Не хвастаюсь, если что... Просто сейчас повторить - не смогу. 20 с лишним лет прошло, что вы хотите?

cadaber ★★
()
Последнее исправление: cadaber (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.