1

我正在处理一些对于 PHP 来说太大而无法处理的数字(二进制​​的 IPv6 地址),所以为了解决这个问题,我制定了一个函数来将地址转换为二进制字符串(实际上只是一个字符串1 和 0)。然而,当谈到子网计算时,我知道如何做到这一点的最简单方法是使用二进制数学。我不知道在这种情况下如何使用二进制数学,因为我在技术上处理的是字符串,而不是二进制数。有什么办法可以用二进制数的字符串表示来进行二进制数学吗?

4

2 回答 2

2

处理大二进制数时,您可以使用GMP 扩展。它接受任意长度的字符串作为参数。

于 2013-05-13T19:00:20.623 回答
0

仔细想想,答案其实很简单。我刚刚编写了自己的函数来将数组拆分为 32 个字符的段(以允许 32 位系统兼容,因为 2^32 是 32 位 PHP 实现中可以达到的最高整数),对每个段执行操作分段,然后将其拼凑起来。但是,该函数强制执行长度为 128 的二进制字符串(如果传入较短的字符串,则填充较短的字符串),这就是我所需要的。它可以很容易地修改以允许任何长度的二进制字符串。这是功能:

function ipm_binmath($a, $b, $operand){
    $binregex = "/\b[01]*\b/";
    if (strlen($a) > 128 || strlen($b) > 128){
        throw new Exception("ipm_binmath accepts binary strings no greater than 128 characters.");
    }

    preg_match($binregex, $a, $amatches);
    preg_match($binregex, $b, $bmatches);

    if ($amatches[0] != $a){
        throw new Exception("Invalid data passed to ipm_binmath - \$a is not a binary string.");
    }
    if ($bmatches[0] != $b){
        throw new Exception("Invalid data passed to ipm_binmath - \$b is not a binary string.");
    }

    $aarr = str_split(str_pad($a, 128, "0", STR_PAD_LEFT), 32);
    $barr = str_split(str_pad($b, 128, "0", STR_PAD_LEFT), 32);
    $ret = "";

    for ($i=0; $i<4; $i++){
        switch (strtoupper(trim($operand))){
            case "AND":
                $ret .= str_pad(decbin((bindec($aarr[$i]) & bindec($barr[$i]))), 32, "0", STR_PAD_LEFT);
                break;
            case "OR":
                $ret .= str_pad(decbin((bindec($aarr[$i]) | bindec($barr[$i]))), 32, "0", STR_PAD_LEFT);
                break;
            case "XOR":
                $ret .= str_pad(decbin((bindec($aarr[$i]) ^ bindec($barr[$i]))), 32, "0", STR_PAD_LEFT);
                break;
            default:
                throw new Exception("Unsupported or invalid operand passed to ipm_binmath: '" . $operand . "'");
                break;
        }
    }
    return $ret;
}
于 2013-05-13T20:09:41.940 回答