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
1开发者_如何转开发5 = 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)?
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
.
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.
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.
精彩评论