2013-05-13 4 views
1

PHP가 처리하기에는 너무 큰 숫자 (IPv6 주소는 바이너리)로 작업하고 있으므로이 문제를 해결하기 위해 이진 문자열에서 주소를 /로 변환하는 함수를 공식화했습니다. 1과 0의 문자열). 그러나 서브넷 계산에 관해서는이 방법을 알고있는 가장 쉬운 방법은 이진 수학을 사용하는 것입니다. 기술적으로 이진수가 아닌 문자열을 다루고 있기 때문에이 인스턴스에서 어떻게 이진수 연산을 사용할지 모르겠습니다. 이진수의 문자열 표현으로 이진 수학을 할 수있는 방법이 있습니까?PHP에서 바이너리 문자열에 바이너리 연산을 수행 할 수있는 방법이 있습니까?

+1

어떤 종류의 수학을 찾고 계십니까? 마스킹 & 범위'substr' 때문에'strcmp'와'str_repeat'가 거의 충분할 것입니다. – Wrikken

+0

글쎄, 확실히 AND와 OR, 아마 XOR. 더 많은 것이있을 수 있지만, 나는 확실히이 세가지가 필요할 것임을 압니다. – Skyline969

+2

글쎄,이 경우 [GMP 기능] (http://www.php.net/manual/en/ref.gmp.php)이 도움이 될 수 있습니다. – Wrikken

답변

2

큰 이진수로 작업 할 때 GMP extension을 사용할 수 있습니다. 매개 변수로 임의의 길이의 문자열을 허용합니다.

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; 
} 
관련 문제