Skyline969
Skyline969

Reputation: 431

Is there a way to perform binary math on binary strings in PHP?

I'm working with some numbers that would be far too large for PHP to handle (IPv6 addresses in binary), so to work around this I've formulated a function to convert the addresses to/from binary strings (literally just a string of 1s and 0s). However, when it comes to subnet calculations the easiest way I know how to do this is to use binary math. I have no idea how I'd use binary math in this instance since I'm technically dealing with strings, not binary numbers. Is there any way I can do binary math with a string representation of a binary number?

Upvotes: 1

Views: 221

Answers (2)

Skyline969
Skyline969

Reputation: 431

The answer was actually simple once I thought about it. I just wrote my own function to split the array into 32-character segments (to allow for 32-bit system compatibility, since 2^32 is the highest an integer can be on a 32-bit PHP implementation), perform the operation on each segment, and piece it back together afterward. However, the function enforces a binary string length of 128 (padding shorter ones if they're passed in) which is all I need. It could be easily reworked to allow any length of binary string. Here is the function:

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

Upvotes: 0

Expedito
Expedito

Reputation: 7795

When working with large binary numbers you could use the GMP extension. It accepts strings of arbitrary length as parameters.

Upvotes: 2

Related Questions