title: How does similar_text work?
body: <p>I just found the similar_text function and was playing around with it, but the percentage output always suprises me. See the examples below. </p>
  
  <p>I tried to find information on the algorithm used as mentioned on <a href="http://php.net/manual/en/function.similar-text.php">php: <code>similar_text()</code><sup><em>Docs</em></sup></a>:</p>
  
  <pre><code>&lt;?php
  $p = 0;
  similar_text('aaaaaaaaaa', 'aaaaa', $p);
  echo $p . "&lt;hr&gt;";
  //66.666666666667
  //Since 5 out of 10 chars match, I would expect a 50% match
  
  similar_text('aaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
  echo $p . "&lt;hr&gt;";
  //40
  //5 out of 20 &gt; not 25% ?
  
  similar_text('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
  echo $p . "&lt;hr&gt;"; 
  //9.5238095238095 
  //5 out of 100 &gt; not 5% ?
  
  
  //Example from PHP.net
  //Why is turning the strings around changing the result?
  
  similar_text('PHP IS GREAT', 'WITH MYSQL', $p);
  echo $p . "&lt;hr&gt;"; //27.272727272727
  
  similar_text('WITH MYSQL', 'PHP IS GREAT', $p);
  echo $p . "&lt;hr&gt;"; //18.181818181818
  
  ?&gt;
  </code></pre>
  
  <p>Can anybody explain how this actually works?</p>
  
  <p><strong>Update:</strong></p>
  
  <p>Thanks to the comments I found that the percentage is actually calculated using the number of similar charactors * 200 / length1 + lenght 2</p>
  
  <pre><code>Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);
  </code></pre>
  
  <p>So that explains why the percenatges are higher then expected. With a string with 5 out of 95 it turns out 10, so that I can use.</p>
  
  <pre><code>similar_text('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaa', $p);
  echo $p . "&lt;hr&gt;"; 
  //10
  //5 out of 95 = 5 * 200 / (5 + 95) = 10
  </code></pre>
  
  <p>But I still cant figure out why PHP returns a different result on turning the strings around. The JS code provided by dfsq doesn't do this. Looking at the source code in PHP I can only find a difference in the following line, but i'm not a c programmer. Some insight in what the difference is, would be appreciated.</p>
  
  <p>In JS:</p>
  
  <pre><code>for (l = 0;(p + l &lt; firstLength) &amp;&amp; (q + l &lt; secondLength) &amp;&amp; (first.charAt(p + l) === second.charAt(q + l)); l++);
  </code></pre>
  
  <p>In PHP: (php_similar_str function)</p>
  
  <pre><code>for (l = 0; (p + l &lt; end1) &amp;&amp; (q + l &lt; end2) &amp;&amp; (p[l] == q[l]); l++);
  </code></pre>
  
  <p>Source:</p>
  
  <pre><code>/* {{{ proto int similar_text(string str1, string str2 [, float percent])
     Calculates the similarity between two strings */
  PHP_FUNCTION(similar_text)
  {
    char *t1, *t2;
    zval **percent = NULL;
    int ac = ZEND_NUM_ARGS();
    int sim;
    int t1_len, t2_len;
  
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Z", &amp;t1, &amp;t1_len, &amp;t2, &amp;t2_len, &amp;percent) == FAILURE) {
      return;
    }
  
    if (ac &gt; 2) {
      convert_to_double_ex(percent);
    }
  
    if (t1_len + t2_len == 0) {
      if (ac &gt; 2) {
        Z_DVAL_PP(percent) = 0;
      }
  
      RETURN_LONG(0);
    }
  
    sim = php_similar_char(t1, t1_len, t2, t2_len);
  
    if (ac &gt; 2) {
      Z_DVAL_PP(percent) = sim * 200.0 / (t1_len + t2_len);
    }
  
    RETURN_LONG(sim);
  }
  /* }}} */ 
  
  
  /* {{{ php_similar_str
   */
  static void php_similar_str(const char *txt1, int len1, const char *txt2, int len2, int *pos1, int *pos2, int *max)
  {
    char *p, *q;
    char *end1 = (char *) txt1 + len1;
    char *end2 = (char *) txt2 + len2;
    int l;
  
    *max = 0;
    for (p = (char *) txt1; p &lt; end1; p++) {
      for (q = (char *) txt2; q &lt; end2; q++) {
        for (l = 0; (p + l &lt; end1) &amp;&amp; (q + l &lt; end2) &amp;&amp; (p[l] == q[l]); l++);
        if (l &gt; *max) {
          *max = l;
          *pos1 = p - txt1;
          *pos2 = q - txt2;
        }
      }
    }
  }
  /* }}} */
  
  
  /* {{{ php_similar_char
   */
  static int php_similar_char(const char *txt1, int len1, const char *txt2, int len2)
  {
    int sum;
    int pos1, pos2, max;
  
    php_similar_str(txt1, len1, txt2, len2, &amp;pos1, &amp;pos2, &amp;max);
  
    if ((sum = max)) {
      if (pos1 &amp;&amp; pos2) {
        sum += php_similar_char(txt1, pos1,
                    txt2, pos2);
      }
      if ((pos1 + max &lt; len1) &amp;&amp; (pos2 + max &lt; len2)) {
        sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max,
                    txt2 + pos2 + max, len2 - pos2 - max);
      }
    }
  
    return sum;
  }
  /* }}} */
  </code></pre>
  
  <p>Source in Javascript: <a href="http://phpjs.org/functions/similar_text/">similar text port to javascript</a></p>