В PHP (или любом другом языке) Можно ли объединить 2 битовые маски, сохраняя при этом "идентичность" исходных битов?


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

Итак, вот сценарий:

У пользователей есть 3 варианта для каждого дня недели: утро, вечер и ВЫХОДНОЙ. Это взаимоисключающие варианты, поэтому нет возможности работать как утром, так и вечером в один и тот же день.

Итак, если бы я хотел сохранить их смены AM и смены PM в виде отдельных битовых масок, а Пользователь1 выбрал бы следующее:

 S    M   T   W   Th   F   Sa
 A    P   X   A   X    P   A

Я бы хотел следующее:

 $shifts['User1']['AM'] = 73;  //  1001001
 $shifts['User1']['PM'] = 34;  //  0100010

Теперь, если бы я просто хотел знать, в какие дни работал Пользователь1, я, очевидно, мог бы просто сделать:

 $shifts['User1']['All'] = $shifts['User1']['AM'] | $shifts['User1']['PM'];

Или даже просто:

 $shifts['User1']['All'] = $shifts['User1']['AM'] + $shifts['User1']['PM'];

Но что, если бы я хотел, чтобы конечный результат отличал AM от PM, что-то вроде:

 $shifts['User1']['AM'] = A00A00A;
 $shifts['User1']['PM'] = 0P000P0;

Так что A и P считаются заданными, но это

 A00A00A | 0P000P0 = AP0A0PA;

Есть ли общий способ сделать это, или я думаю об этом совершенно неправильно?

Author: Anthony, 2012-03-25

5 answers

Для представления трех состояний двоичным способом вам нужно 2 бита. Например, вы могли бы сказать, что:

PM= 01

AM = 10

ВЫКЛ = 00

Итак, теперь у вас есть это:

A00A00A переводится как 10 00 00 10 00 00 10

0P000P0 переводится как 00 01 00 00 00 01 00

Применение побитовой операции ИЛИ:

10 00 00 10 00 00 10
00 01 00 00 00 01 00
--------------------
10 01 00 10 00 01 10
A  P  0  A  0  P  A

Вы получаете AP0A0PA желаемый результат.

 1
Author: Telmo Marques, 2012-03-25 03:11:48

Для записи буквального значения в двоичном виде используйте: 0b1001001 или шестнадцатеричное: 0x49 вместо десятичного: 73.

Растровое изображение всегда будет давать вам только значение true или false, поэтому невозможно представить три значения (AM, PM, X), сжав два растровых изображения в одно.

Я думаю, что вы думаете об этом неправильно (у других может быть более разумное решение, о котором я не могу думать). Массив символов A, P, X может быть так же хорош для этого. Вы можете объединять массивы (так что это не то же самое, что строка).

 1
Author: Paul, 2012-03-25 02:19:27

Да, это возможно. Смотрите пример ниже на Python:

>>> class WorkShift(str):
    def __or__(self, val):
        def shift_calc(x, y):
            return x if x != '0' else y
        return WorkShift(''.join(map(shift_calc, self, val)))

>>> WorkShift('A00A00A') | WorkShift('0P000P0')
'AP0A0PA'

Отвечает ли это на ваш вопрос?

Пс. Я использовал Python, так как вы явно заявили, что это может быть любой язык программирования. Я перегрузил оператор |. Результатом операции по-прежнему является экземпляр WorkShift, поэтому вы можете использовать его для дальнейшей обработки. Он также наследуется от str, поэтому вы также можете использовать его в качестве строки.

РЕДАКТИРОВАТЬ:

Аналогичное решение для PHP, но без перегрузки операторов, основано только на обработке строк:

<?php

function shift_calc($x, $y) {
    return $x != '0' ? $x : $y;
};

function shift_sum($am, $pm) {
    return implode(array_map('shift_calc', str_split($am), str_split($pm)));
};

$result = shift_sum('A00A00A', '0P000P0');

Где $result - строка со следующим значением: "AP0A0PA" (см. Доказательство здесь: http://ideone.com/NbTEJ).

 1
Author: Tadeck, 2012-03-25 02:41:04

Комментарий Minitech верен. Это троичная система счисления (потому что у вас есть 3 варианта для каждого значения). Таким образом, вы могли бы сделать это:

$shifts['User1']['AM'] = '1001001';  //  A00A00A
$shifts['User1']['PM'] = '0200020';  //  0P000P0

$all = intval($shifts['User1']['AM'], 3) +
    intval($shifts['User1']['PM'], 3);

echo base_convert($all, 10, 3);
 1
Author: Paul, 2012-03-25 03:02:52

Здесь у вас есть два варианта.

  1. Чередование

    Исходная битовая маска раскладывается, а новая битовая маска вставляется в новые "отверстия".

    APAPAPAPAPAPAP
    
  2. Добавить

    Новая битовая маска добавляется к старой битовой маске.

    AAAAAAAPPPPPPP
    

Первое легче проверить/сравнить, но второе более эффективно в отношении скорости.

 0
Author: Ignacio Vazquez-Abrams, 2012-03-25 02:07:52