2012-02-13 5 views
7

나는 C# 용 메타 폰 구현을 테스트하고 그 결과를 PHP의 내장 metaphone() 함수와 비교하고있다. 그러나 나는 버그를 만났고 (previously documented in PHP's issue tracker이고, a mailing list에 대해 논의했다.) 나는 내 자신의 개인적인 이익을 위해 버그 뒤에있는 C 코드를 이해하려고 노력하고있다.PHP 메타 폰 구현 버그

기본적으로 메타 폰 알고리즘에 따르면 대부분의 -gh- 인스턴스는 무음으로 렌더링되어야합니다. "라이트"의 특정 테스트 케이스에서, 나는 기대 (그리고 내 자신의 알고리즘으로 생성)

"wr" => R 
"i" => ignored 
"gh" => ignored 
"t" => T 

Result: RT 

그러나 "RT"의 메타 폰 키를, PHP의 메타 폰 기능은 RFT를 반환합니다. 분명히 단어의 끝 부분에있는 것처럼 (예 : "거친") F를 F로 변환하지만, 단어 "wright"의 경우에는 -gh-가 말의 끝에 오지 마라. 다음 라인 (342)에

/* These prevent GH from becoming F */ 
#define NOGHTOF(c) (ENCODE(c) & 16) /* BDH */ 

... 

/* Go N letters back. */ 
#define Look_Back_Letter(n) (w_idx >= n ? toupper(word[w_idx-n]) : '\0') 

그리고 :

case 'G': 
    if (Next_Letter == 'H') { 
     if (!(NOGHTOF(Look_Back_Letter(3)) || Look_Back_Letter(4) == 'H')) { 
      Phonize('F'); 
      skip_letter++; 

누군가가 나에게 무엇을 정확하게 NOGHTOF 기능을 이해하는 데 도움이 할 수있는 PHP 소스 배포판의 metaphone.c 파일을 보면, 나는 몇 가지 주요 사물을 그리고 왜이 코드가 -gh- in "wright"에 대해 F를 잘못 렌더링 했는가? 나는 정말로 C 녀석이 아니기 때문에 코드가 나에게 분명하지 않다.

+1

그러면 누군가가 목록에 패치를 제출하여이 버그를 해결할 수 있습니다! –

+0

이렇게 다음과 같은 질문이 필요합니다. –

답변

1

NOGHTOF(c)의 의미는 실제로 라인 (81)에서 시작하는 코드에 의해 결정된다 : 위해

char _codes[26] = { 
     1, 16, 4, 16, 9, 2, 4, 16, 9, 2, 0, 2, 2, 2, 1, 4, 0, 2, 4, 4, 1, 0, 0, 0, 8, 0 
    /* a b c d e f g h i j k l m n o p q r s t u v w x y z */ 
}; 

#define ENCODE(c) (isalpha(c) ? _codes[((toupper(c)) - 'A')] : 0) 

본질적으로 가치가 알파벳의 각 문자에 할당한다 (A = 1, B = 16, 등등) 그런 다음 ENCODE 매크로는 전달 된 문자가 문자인지 검사합니다. 예이면 해당 문자의 해당 코드를 반환하고 그렇지 않으면 null 문자를 반환합니다. (실제 호출을 대체하기 위해 매크로가 컴파일 타임에 컴파일러에 의해 대체되므로 실제로 아무것도 반환하지 않습니다.) 에 대한 코드를 읽는 방법은 다음과 같습니다. 왜) 이해 :

If current letter is G then 
    If next letter is H then 
     Take "_code" value of a letter three letters back (why?) from the _codes table and check the fifth bit (from the back, naturally) 
     If this bit is not set OR if a letter four letters back (why?) is 'H' then 
      Add 'F' to the result 
      skip one more character (letter 'H' following the 'G') 

가이 같은 이유

그래도 나를 넘어, 나는 누군가가 이런 식으로 작성하는 좋은 이유가 확신 해요,하지만 그것은 나에게 명백한 버그를 보인다.

+0

Thanks. 비트 수준 연산자에 대해서는 어느 정도 익숙합니다. 정확히 16 비트의 숫자와 마지막 4 비트의 비트를 지우는 것이 정확히 무엇인지 말해 줄 수 있습니까? – Chris

+0

먼저 내 실수는 마지막 4 비트를 지우지 않는 것입니다. 다섯 번째 비트가 설정되어 있는지 확인합니다. 내 대답을 업데이트하고 있습니다. 이제는 숫자를 다루지 않고 한 바이트 (8 비트) : xxxxxxxx 바이너리 만 사용합니다. 이진수 16은 00010000입니다. 이제 비트 AND는 두 숫자의 해당 비트를 가져와 두 비트가 모두 1 인 경우에만 해당 비트를 1로 설정하여 새 숫자를 만듭니다. –

+0

오른쪽에 & 연산자가 있습니다. 나는 그것이 비트 5가 설정되어 있는지보기 위해 점검하고 있다고 생각했지만 당신의 대답으로 혼란스러워했다. 그 문제를 해결해 주셔서 감사합니다. 그런데 G가 나오기 전에 세 번째 글자가 ('B', 'D', 'H')인지 확인하는 것이 왜 조용하게 되리라는 것을 확인하는 것은 매우 불확실합니다. 아마 원래의 코더가이 방식으로 선택된 몇 개의 단어를 목표로 삼고 있었을 것입니다. (bough와 dough는 얻을 수 있지만 hough?) 의심 할 여지없이 코드는 엉뚱한 버그입니다. 추가적인 통찰력에 감사드립니다. – Chris