Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PHP(或任何语言)中,可以合并2个位掩码,同时保持;“身份”;原始比特数?_Php_Bit Manipulation - Fatal编程技术网

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

在PHP(或任何语言)中,可以合并2个位掩码,同时保持;“身份”;原始比特数?,php,bit-manipulation,Php,Bit Manipulation,这可能是一个非常愚蠢的问题,但它只是在我脑海中闪过,我想肯定知道它会很有趣 下面是一个场景: 用户一周中的每一天都有3个选项:上午、下午和下班。这些都是相互排斥的选择,因此没有选择在同一天的上午和下午同时工作 因此,如果我想将其AM移位和PM移位存储为单独的位掩码,并且User1选择以下选项: S M T W Th F Sa A P X A X P A $shifts['User1']['AM'] = 73; // 1001001

这可能是一个非常愚蠢的问题,但它只是在我脑海中闪过,我想肯定知道它会很有趣

下面是一个场景:

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

因此,如果我想将其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
我希望:

 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;

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

您有两种选择

  • 交错

    原始位掩码展开,新位掩码插入新的“孔”

  • 附加

    新的位掩码将附加到旧的位掩码


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

    这里有两个选项

  • 交错

    原始位掩码展开,新位掩码插入新的“孔”

  • 附加

    新的位掩码将附加到旧的位掩码


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

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

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


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

    要以二进制形式写入文字值,请使用:
    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'
    
    它回答了你的问题吗

    另外,我使用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');
    

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

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

    PM=01

    AM=10

    关=00

    现在你有了这个:

    A00A00A
    转换为
    10000010

    0P000P0
    转换为
    0001 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

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

    PM=01

    AM=10

    关=00

    现在你有了这个:

    A00A00A
    转换为
    10000010

    0P000P0
    转换为
    0001 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
    

    您将获得所需的结果。

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

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

    我想到了两件事:三元的,普通的,不使用位掩码来完成这类任务。哦,在一天结束时,我肯定我会将它们分开,或者使用其他逻辑来推断,等等。但是As和Ps的图像突然出现在我的脑海中,我想可能是“不,傻瓜,这就是它现在的工作方式”或者“哼,换个基数就行了“,所以我不得不把它扔到那里去确定。我想到了两件事:三元的,普通的,不使用位掩码来完成这类任务。哦,在一天结束时,我确定我要么将它们分开,要么使用其他逻辑来推断,等等。但是As和Ps的图像突然出现在我的脑海中,我想可能是其中之一“不,傻瓜,这就是它现在的工作原理”或“嗯,只是改变基数”,所以我不得不把它扔出去,以确定它是可以做到的。+1表示它可以做到。现在我只需要拿出我的反向工程帽,看看它是否可以在PHP中复制。@Anthony:是的,它可以实现。请参见PHP<5.3的示例(对于PHP>=5.3,它会更好):让我把它复制到我的本地服务器上