简体   繁体   中英

Error in algorithm

I have a script:

function convert($src, $srcAlphabet = '0123456789', $dstAlphabet =
    'qwertyuiopasdfghjklzxcvbnm')
{
    $srcBase = strlen($srcAlphabet);
    $dstBase = strlen($dstAlphabet);

    $wet = $src;
    $val = 0;
    $mlt = 1;

    while($l = strlen($wet))
    {
        $digit = $wet[$l - 1];
        $val += $mlt * strpos($srcAlphabet, $digit);
        $wet = substr($wet, 0, $l - 1);
        $mlt *= $srcBase;
    }

    $wet = $val;
    $dst = '';

    while($wet >= $dstBase)
    {
        $digitVal = $wet % $dstBase;
        $digit = $dstAlphabet[$digitVal];
        $dst = $digit . $dst;
        $wet /= $dstBase;
    }

    $digit = $dstAlphabet[$wet];
    $dst = $digit . $dst;

    return $dst;
}

for($i = 0; $i < 10000; $i++)
{
    echo $i . ' = ' . convert(substr(' ' . $i, 1)) . '<br>';
}

It works fine, however the result is strange... it looks like that:

0 = q
1 = w
2 = e
3 = r
4 = t
5 = y
6 = u
7 = i
8 = o
9 = p
10 = a
11 = s
12 = d
13 = f
14 = g
15 = h
16 = j
17 = k
18 = l
19 = z
20 = x
21 = c
22 = v
23 = b
24 = n
25 = m
26 = wq
...
...
676 = wqq
677 = wqw
678 = wqe
...

but 26 should be qq, 676 should be qqq, 677 = qwq, 678 = qqe etc.

why it's starting from w instead of q (except for 0)?

After a long time of looking on your algorithm, I finally get what you wanted ^^

Firstly, PHP has many builtin methods that would help you a lot. If I am not wrong, the following part of your code is only to convert $src to an integer.

while($l = strlen($wet))
{
    $digit = $wet[$l - 1];
    $val += $mlt * strpos($srcAlphabet, $digit);
    $wet = substr($wet, 0, $l - 1);
    $mlt *= $srcBase;
}

Not only that you "cast" it to a string in a strange way before calling the function, you also "cast" it back to an integer even stranger. You should have a look on php's intval method. And the reason that it always begins with w is simply that the second loop only continues if

$digitVal = $wet % $dstBase >= $dstBase

which means that in the next step it will still be $digitVal > 1 , so the index is minimum 1, which corresponds to w . Actually, this makes sense in a way even though I don't know what exactly you want to accomplish (change the base of your number to 26?), because 0 exists as well, but there is no number such as 009 or something similar. You then just write 9 and it's the same in your system (you only write p instead of qqp).

However, you should really learn some tricks in PHP to make your life easier. Have a look on this tutorial.

q represents 0 . And obviously the script you've found does a base conversion. To differentiate 0 from 26 it needs to represent the values differently.

Because q is already 0 it cannot use qq for 26, because that would be tantamount to 00 . It needs the first letter to represent a 1, so it uses wq .

I think you're trying to say that 677 should equal qqw, no?

In any event, you could do something much easier to (this is pseudo php, obviously)

function convert($src, $srcAlphabet = '0123456789', $dstAlphabet =
    'qwertyuiopasdfghjklzxcvbnm')
{

  $lenAlphabet = strlen($dstAlphabet);
  $tempSrc = $src;

  $result = '';
  while($tempSrc / $lenAlphabet > 0){                
             $tempSrc = $tempSrc / $lenAlphabet;
             $result .= $dstAlphabet[Math.Max(0,($tempSrc % $lenAlphabet) - 1)];

        }      
  return $result . $dstAlphabet[$src % $lenAlphabet];
 }

Sorry about the Math.Max (I wrote this in C# and tried to pseudo convert it). the reason for the Math.Max is that when the $src value is a perfect square, cube, quart, etc. the expression evaluates to -1. Also note that due to the definition of your series, there are 26 values that are not possible in the given range 0-676: they consist of the mq, mw,...mm values.

If you change

$wet /= $dstBase;

to

$wet = $wet / $dstBase - 1;

your code will give the correct result. However, as Soren noted, using PHP functionality you can accomplish things much easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM