Reputation: 431
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
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
Reputation: 7795
When working with large binary numbers you could use the GMP extension. It accepts strings of arbitrary length as parameters.
Upvotes: 2