将整数转换为字母,反之亦然(例如 0 =“A”、26 =“AA”、27 =“AB”)

问题描述 投票:0回答:13

所以我有这个功能:

function toAlpha($data){
    $alphabet =   array('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');
    $alpha_flip = array_flip($alphabet);
    if($data <= 25){
      return $alphabet[$data];
    }
    elseif($data > 25){
      $dividend = ($data + 1);
      $alpha = '';
      $modulo;
      while ($dividend > 0){
        $modulo = ($dividend - 1) % 26;
        $alpha = $alphabet[$modulo] . $alpha;
        $dividend = floor((($dividend - $modulo) / 26));
      } 
      return $alpha;
    }
}

给定一个数字将其转换为字符并且工作正常

但是我也想要一个该函数的反向函数,给出该函数的任何输出,返回为产生该输出而输入的确切输入,我尝试了以下方法:

function toNum($data){
$alphabet =   array('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');
    $alpha_flip = array_flip($alphabet);
  if(strlen($data) == 1){
          return (isset($alpha_flip[$data]) ? $alpha_flip[$data] : FALSE);
        }
        else if(strlen($data) > 1){
          $num = 1;
          for($i = 0; $i < strlen($data); $i++){
            if(($i + 1) < strlen($data)){
              $num *= (26 * ($alpha_flip[$data[$i]] + 1));
            }
            else{
              $num += ($alpha_flip[$data[$i]] + 1);
            }
          }
          return ($num + 25);
        }
}

但它无法正常工作...toAlpha(728) 正在生成 'aba' 但 toNum('aba') 正在生成 1378 而不是 728...

我做错了什么?如何修复反向功能使其正常工作?

php string math reverse data-conversion
13个回答
157
投票

最短的方法,PHP >= 4.1.0

$alphabet = range('A', 'Z');

echo $alphabet[3]; // returns D

echo array_search('D', $alphabet); // returns 3

17
投票

我完全不明白你试图在该函数中使用的逻辑。你想要做的事情看起来很奇怪(为什么'a'映射到零而'aa'映射到26?),但这似乎有效。 (您将需要使用更多测试用例,我只检查它是否为案例“aba”提供了正确的输出。)

function toNum($data) {
    $alphabet = array( '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'
                       );
    $alpha_flip = array_flip($alphabet);
    $return_value = -1;
    $length = strlen($data);
    for ($i = 0; $i < $length; $i++) {
        $return_value +=
            ($alpha_flip[$data[$i]] + 1) * pow(26, ($length - $i - 1));
    }
    return $return_value;
}

16
投票

Theriault 在 PHPs base_convert 函数

的注释中有一个非常聪明的解决方案
/**
* Converts an integer into the alphabet base (A-Z).
*
* @param int $n This is the number to convert.
* @return string The converted number.
* @author Theriault
* 
*/
function num2alpha($n) {
    $r = '';
    for ($i = 1; $n >= 0 && $i < 10; $i++) {
    $r = chr(0x41 + ($n % pow(26, $i) / pow(26, $i - 1))) . $r;
    $n -= pow(26, $i);
    }
    return $r;
}
/**
* Converts an alphabetic string into an integer.
*
* @param int $n This is the number to convert.
* @return string The converted number.
* @author Theriault
* 
*/
function alpha2num($a) {
    $r = 0;
    $l = strlen($a);
    for ($i = 0; $i < $l; $i++) {
    $r += pow(26, $i) * (ord($a[$l - $i - 1]) - 0x40);
    }
    return $r - 1;
}

8
投票

从数字到字母(A=0,B=1,等等...):

function toAlpha($num){
    return chr(substr("000".($num+65),-3));
}

您可以使用功能

ord()
从字母到数字执行相同的操作。

将65换成97,即可得到小写值。


5
投票

你的问题来自于你的地图。看看这个:

$alpha[0] = 'Alphabet';
for ($i = 'a'; $i<'z'; $i++) {
    $alpha[] = $i;
}
$alpha[26] = 'z';

您可以在服务器内存允许的情况下运行任意高的值。 PHP 是有 bug 的,并且(至少在我的服务器上)如果你使用 <= operator:

$alpha[0] = 'Alphabet';
for ($i = 'a'; $i<='z'; $i++) {
    $alpha[] = $i;
}

然后它将一直映射到 [676]=> string(2) "yz"!你只需要玩它。

我不想将字母映射到 [0],所以我只是在其中放置了一个标题。显然,如果你想要 0=>a、1=>b 等,你可以省略它。

一旦数组正确,该函数就很简单了。


5
投票

使用西里尔的回答,我对一个包含多个字母的案例进行了一些详细说明。

function lettersToNumber($letters){
    $alphabet = range('A', 'Z');
    $number = 0;

    foreach(str_split(strrev($letters)) as $key=>$char){
        $number = $number + (array_search($char,$alphabet)+1)*pow(count($alphabet),$key);
    }
    return $number;
}

该函数的一些结果显示如下:

lettersToNumber("A"); //returns 1
lettersToNumber("E"); //returns 5
lettersToNumber("Z"); //returns 26
lettersToNumber("AB"); //returns 28
lettersToNumber("AP"); //returns 42
lettersToNumber("CE"); //returns 83

4
投票

将数字转换为字母代码

例如:1402转bax

function number_to_alpha($num, $code)
{   
    $alphabets = array('', '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');

    $division = floor($num / 26);
    $remainder = $num % 26; 

    if($remainder == 0)
    {
        $division = $division - 1;
        $code .= 'z';
    }
    else
        $code .= $alphabets[$remainder];

    if($division > 26)
        return number_to_alpha($division, $code);   
    else
        $code .= $alphabets[$division];     

    return strrev($code);
}

将字母代码转换为数字

例如:bax转1402

function alpha_to_number($code)
{
    $alphabets = array('', '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');

    $sumval = 0;

    $code = strtolower(trim($code));

    $arr = str_split($code);
    $arr_length = count($arr);

    for($i = 0, $j = $arr_length-1; $i < $arr_length; $i++, $j--)
    {
        $arr_value = array_search($arr[$i], $alphabets);
        $sumval = $sumval + ($arr_value * pow(26, $j));
    }

    return $sumval;
}

2
投票

我采用了“更正”的原件,删除了调试代码和其他不必要的代码,对其进行了修改,以便它可以处理任意数量的字符。例如,希腊语只有 24 个字符。

function toAlpha($number, $alphabet)
    {

        $count = count($alphabet);
        if ($number <= $count) {
            return $alphabet[$number - 1];
        }
        $alpha = '';
        while ($number > 0) {
            $modulo = ($number - 1) % $count;
            $alpha  = $alphabet[$modulo] . $alpha;
            $number = floor((($number - $modulo) / $count));
        }
        return $alpha;
    }

    toAlpha(45,range('a','z'));

以下是一些范围示例:

// lower greek
$range = ['α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'];
// upper greek 
$range = ['Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω'];
// georgian 
$range = ['ჵ' => 10000, 'ჰ' => 9000, 'ჯ' => 8000, 'ჴ' => 7000, 'ხ' => 6000, 'ჭ' => 5000, 'წ' => 4000, 'ძ' => 3000, 'ც' => 2000, 'ჩ' => 1000, 'შ' => 900, 'ყ' => 800, 'ღ' => 700, 'ქ' => 600, 'ფ' => 500, 'ჳ' => 400, 'ტ' => 300, 'ს' => 200, 'რ' => 100, 'ჟ' => 90, 'პ' => 80, 'ო' => 70, 'ჲ' => 60, 'ნ' => 50, 'მ' => 40, 'ლ' => 30, 'კ' => 20, 'ი' => 10, 'თ' => 9, 'ჱ' => 8, 'ზ' => 7, 'ვ' => 6, 'ე' => 5, 'დ' => 4, 'გ' => 3, 'ბ' => 2, 'ა' => 1];

0
投票

这是对原始函数 toAlpha 的修复。它不适用于 toAlpha(27)

function toAlpha($n,$case = 'upper'){
    $alphabet   = array('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');
    $n = $n-1;
    Util::error_log('N'.$n);
    if($n <= 26){
        $alpha =  $alphabet[$n-1];
    } elseif($n > 26) {
        $dividend   = ($n);
        $alpha      = '';
        $modulo;
        while($dividend > 0){
            $modulo     = ($dividend - 1) % 26;
            $alpha      = $alphabet[$modulo].$alpha;
            $dividend   = floor((($dividend - $modulo) / 26));
        }
    }

    if($case=='lower'){
        $alpha = strtolower($alpha);
    }
    Util::error_log("**************".$alpha);
    return $alpha;

}

0
投票

我们可以将数字从十进制(基数 10)转换为字母数字(基数 36),并使用

base_convert()
:

将位置从数字块移动到字母块
function toLetter(int $num) {
    return strtoupper(base_convert($num + 9, 10, 36));
}

0
投票

我这样做是为了在 int 参数之前使用修复字符长度 A = 0,Z = 25

function returnUIDfixChar(int $inc,int $charlength=3,int $min_input_length=3,string $prefix=''):string {
$alpha = range('A','Z');
$max_alpa_int = count($alpha)-1;
$over = 0;
$output_prefix = '';
$first_split = 0;
if(strlen($inc)>$min_input_length)
{
    $first_split = substr((string) $inc,0,strlen($inc)-$min_input_length);
}
$second_split = substr((string) $inc,0,$min_input_length);
for($i=0;$i<$charlength;$i++)
{
    $temp_over = (float) $first_split - $max_alpa_int;
    if($temp_over>0)
    {
        $output_prefix = $alpha[$max_alpa_int].$output_prefix;
        $first_split -= $max_alpa_int;
    }
    elseif($first_split<$max_alpa_int && $first_split>0)
    {
        $output_prefix = $alpha[$first_split].$output_prefix;
        $first_split -= $first_split;
    }
    else
    {
        $output_prefix = $alpha[0].$output_prefix;
    }
    $over = $first_split;
}
if(strlen($second_split)<$min_input_length)
{
    for($i=0;$i<$min_input_length-strlen($second_split);$i++)
    {
        $second_split = '0'.$second_split;
    }
}
return $output_prefix.($first_split>0?$first_split:'').$second_split;

}


0
投票

这是一个可以使用非常高的列值(超过两个字母)的实现:

function columnNumberToLetter($columnNumber) {
    $columnLetter = '';
    while ($columnNumber >= 0) {
        $modulus = $columnNumber % 26;
        $columnLetter = chr(65 + $modulus) . $columnLetter;
        $columnNumber = intval($columnNumber / 26) - 1;
    }
    return $columnLetter;
}

echo columnNumberToLetter(28); // output: AC

如果您想将单元格引用的数字数组转换为电子表格范围,您可以添加以下内容:

function rangeToString($range) {
    // Convert column numbers to letters
    $startColumn = columnNumberToLetter($range[0][0]);
    $endColumn = columnNumberToLetter($range[1][0]);

    // Convert row indices to spreadsheet row numbers
    $startRow = $range[0][1] + 1;
    $endRow = $range[1][1] + 1;

    // Combine to form range string
    return $startColumn . $startRow . ':' . $endColumn . $endRow;
}

echo rangeToString([[0,0],[27,5]]); // Output: A1:AB6

当您与 Google Sheets API 集成时,此类代码非常有用。例如,如果您想获取所有冻结行和列的引用,这些行和列以整数而不是单元格引用的形式提供。


-2
投票
function toNum($str) {
  $num = 0;
  for ($i = 0; $i < strlen($str); $i++) {
    $num += ord($str[$i]);
    $num *= 26;
  }
  return $num;
}

function toStr($num) {
  $str = '';
  while ($num > 0) {
    $str = chr($num % 26) . $str;
    $num = (int) ($num / 26);
  }
  return $str;
} 
© www.soinside.com 2019 - 2024. All rights reserved.