我想创建一个用户友好的系统来让用户输入某个id:
id 1-26: A-Z
27: AA
28: AB
...
...
ZZZ
我尝试了几种方法来实现这一点,但我得到了随机字符......
$counter = 7;
do {
$temp = floor($id / (26^$counter)) % 26;
$counter--;
echo($temp.' ');
} while($counter > 0);
我想创建一个用户友好的系统来让用户输入某个id:
id 1-26: A-Z
27: AA
28: AB
...
...
ZZZ
我尝试了几种方法来实现这一点,但我得到了随机字符......
$counter = 7;
do {
$temp = floor($id / (26^$counter)) % 26;
$counter--;
echo($temp.' ');
} while($counter > 0);
将 Excel 列名映射到数字顺序是一件很糟糕的事情,因为0
AZ 中没有......
无论如何,我确实想出了两个函数来来回转换它们:
function calcCol($col) //character to number
{
if(is_numeric($col)) return intval($col);
$col=array_reverse(str_split(strtoupper(preg_replace("/[^a-z]/i","",$col))));
$num=0;
foreach($col as $i=>$ch)
{
$num+=(ord($ch)-ord('A')+1)*pow(27,$i);
}
$num-=ceil($num/27)-1;
return $num;
}
function getCol($col) //number to character
{
if(preg_match("/^[a-z]+$/i",$col)) return strtoupper($col);
$col=abs(intval($col));
$col+=ceil($col/26)-1;
$str="";
while($col>0)
{
$tmp=$col%27;
$str=chr($tmp-1+ord('A')).$str;
$col=floor($col/27);
}
return $str;
}
解释:
将 AZ 视为基于27 的数字系统,其中缺少/隐藏0
;
0
并且在从字符转换为数字之后,通过计算“计数”了多少个 27 来删除那些隐藏的 s ( ceil($num/27)
);
0
在从数字转换为字符之前,通过计算“计数”了多少个 26( )将那些隐藏的 s 添加回来ceil($col/26)
。
这是一个碱基转换问题,但有一个小技巧。
首先我们考虑'A'
as 1
, so'AA'
或'AAA'
可能是有意义的, 'B'
as 2
, 'C'
as 3
.., 但是呢'Z'
?不,'Z'
不是 26,这里的技巧是考虑'Z'
as 'A0'
,每次我们0
在转换中找到一个 when 时,我们把它写下来 as 'Z'
,然后扔掉一个'A'
(减去 1)。
所以我们有以下代码:
function num2user( $num )
{
$s = "ZABCDEFGHIJKLMNOPQRSTUVWXYZ";
$ret = "";
while( $num > 0 )
{
$m = $num % 26;
$ret = $s[$m].$ret;
$num = floor($num / 26);
if( $m == 0 ) $num = $num - 1;
}
return $ret;
}
for( $i = 1 ; $i < 128 ; $i++ )
{
echo "$i=".num2user($i)."\n";
}