在PHP(或任何语言)中,2个比特掩码可以在保持“;身份;原始位


In PHP (or any language), Can 2 bitmasks be merged while maintaining "identity" of orignal bits?

这可能是一个非常愚蠢的问题,但我突然想到了这个问题,我想知道这一点会很有趣。。。。

下面是场景:

用户在一周中的每一天都有三个选项:上午、下午和关闭。这三个选项相互排斥,因此没有在同一天同时工作上午和下午的选项。

因此,如果我想将它们的AM偏移和PM偏移存储为单独的位掩码,并且User1选择以下内容:

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

我会有以下内容:

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

现在,如果我只是想知道User1在哪几天工作,我显然可以做:

 $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;

有没有一种常见的方法可以做到这一点,或者我认为这是完全错误的?

要以二进制方式表示三种状态,需要2位。例如,你可以这样说:

PM=01

上午=10

关闭=00

所以现在你有了这个:

A00A00A转换为10 00 00 10 00 00 10

0P000P0转换为00 01 00 00 00 01 00

应用位OR运算:

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,你想要的结果。

要以二进制形式写入文字值,请使用:0b1001001或十六进制:0x49,而不是十进制:73

位图只会给出true或false,因此无法通过将两个位图压缩为一个来表示三个值(AM、PM、X)。

我认为你想错了(其他人可能有我想不出的更聪明的解决方案)。字符A、P、X的数组可能同样适用于此。您可以合并数组(因此它与字符串不同)。

是的,这是可能的。请参阅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'

它能回答你的问题吗?

Ps。我之所以使用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)。

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. 交错

    原来的位掩码展开,新的位掩码插入到新的"孔"中。

    APAPAPAPAPAPAP
    
  2. 附加

    新的位掩码被附加到旧的位掩码。

    AAAAAAAPPPPPPP
    

前者更容易检查/比较,但后者在速度方面更有效。