Traduce números enteros a letras y viceversa (por ejemplo, 0 = “A”, 26 = “AA”, 27 = “AB”)

7 minutos de lectura

avatar de usuario de pillarOfLight
pilardeluz

Así que tengo esta función:

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;
    }
}

que dado un número lo convierte en carácter y funciona bien

pero luego también quiero una función inversa de esto que, dada cualquier salida de esta función, devuelva la entrada exacta que se puso para producir esa salida y probé esto:

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);
        }
}

pero no funciona correctamente… toAlpha(728) está produciendo ‘aba’ pero toNum(‘aba’) está produciendo 1378 en lugar de 728…

¿Qué hice mal? ¿Cómo puedo arreglar la función inversa para que funcione correctamente?

  • Así que estás tratando de convertir un número de base 10 a base 26, ¿es eso?

    – Mathieu Dumoulin

    5 de octubre de 2011 a las 15:57

  • ¿Qué se supone que debe hacer la función toAlpha original? ¿Cuál es el comportamiento deseado si el número es mayor de 25?

    – Alex Turpin

    5 de octubre de 2011 a las 15:57

  • se convierte en letras dobles, letras triples, etc., por ejemplo: 26 = aa, 27 = ab, etc.

    – pilar de luz

    5 de octubre de 2011 a las 15:59

  • Si ‘a’ es tu 0, ¿no debería aa también ser 0? Al menos, si solo está tratando de implementar la base 26 directa usando letras en lugar de números.

    – Hammerita

    5 de octubre de 2011 a las 16:12

  • El resultado deseado de ambas funciones no está claro. ¿Puede explicar qué deben generar exactamente las funciones y según qué reglas?

    – Aficionado decente

    5 de octubre de 2011 a las 16:14

Avatar de usuario de Cyril
Cirilo

Camino más corto, en PHP >= 4.1.0

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

echo $alphabet[3]; // returns D

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

  • Esto no funcionará con ningún número entero que exceda la longitud de la matriz alfabética; por ejemplo, “42”.

    – Kirgy

    26 mayo 2016 a las 10:37

  • @kirgy Publiqué una respuesta basada en este caso que funciona con números enteros que exceden la longitud de la matriz alfabética.

    – rvbarreto

    18 de marzo de 2019 a las 17:10

  • Para una letra, imprimirá el número “0”, es incorrecto, por lo que el nuevo código debería ser: echo array_search($letra, $alfabeto)+1;

    – Bbbb

    25 dic 2022 a las 19:50


  • Esta ha sido la respuesta correcta a la pregunta incorrecta desde que se publicó la pregunta. Las puntuaciones de las respuestas en esta página transmiten un mensaje inapropiado a los investigadores. Esta respuesta no debe tener una puntuación positiva porque no satisface el escrito.

    – mickmackusa

    26 ene a las 20:00


Avatar de usuario de Hammerite
Hammerita

No entiendo en absoluto la lógica que estás tratando de usar en esa función. Lo que está tratando de hacer parece muy extraño (¿por qué ‘a’ se asigna a cero y, sin embargo, ‘aa’ se asigna a 26?), pero parece funcionar. (Querrá usar algunos casos de prueba más, solo comprobé que da el resultado correcto para el caso ‘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;
}

  • En base 10, el sucesor de 9 no es 00. Entonces, ¿por qué aa es el sucesor de z?

    – Hammerita

    6 de octubre de 2011 a las 0:39

  • Excel hace esto. Tal vez @pillarOfLight estaba tratando de resolver algo con hojas de cálculo.

    – Stéphane

    13 de septiembre de 2012 a las 3:03

  • $alfabeto = rango(‘a’, ‘z’);

    – lado oeste

    9 oct 2012 a las 20:51

  • @Hammerite me confundió, pero después del personaje único, el segundo a en aa mueve esto de la base 26 a base 27 ya que tiene un valor posicional (entonces az MÁS la ausencia de una a = 27 caracteres). Es como si 001 101!

    – Se bueno

    6 de noviembre de 2018 a las 12:11

  • Tiempo de preguntas tontas. 1) ¿Por qué necesita ` $alpha_flip = array_flip($alphabet);` y en el original hay una línea $modulo;. Ambos parecen redundantes. 2) Pregunté arriba pero repetiré aquí: ¿Qué hace el %? (He probado Goog, PHP.net, SO, etc. pero buscando con un % es bastante entretenido.)

    – Se bueno

    6 de noviembre de 2018 a las 15:06


Hay una solución muy inteligente de Theriault en los comentarios de Función base_convert de PHP

/**
* 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;
}

  • Funciona muy bien con cualquier número: num2alpha(25) → “Z”, num2alpha(26) → “AA”,…

    – Felipe

    31 de julio de 2020 a las 14:42

  • Consejo: uso 97 en lugar de 0x41 y 96 en lugar de 0x40 para obtener letras minúsculas. O usar strtolower() para convertir el resultado a minúsculas

    – Felipe

    31 de julio de 2020 a las 14:44

Del número al alfabeto (con A=0, B=1, etc…):

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

Puedes hacer lo mismo de alfabeto a número con la función ord().

Cambiando 65 por 97 se obtienen los valores en minúsculas.

Avatar de usuario de Mason Barge
Barcaza de albañil

Tus problemas provienen de tu mapa. Mira este:

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

Puede ejecutar esto tan alto como desee y la memoria de su servidor lo permitirá. El PHP tiene errores y (al menos en mi servidor) si usa el operador

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

luego se mapeará hasta [676]=> cadena(2) “yz”! Sólo tienes que jugar con él.

No quería asignar una carta a [0] así que solo puse un título allí. Obviamente puedes omitirlo si quieres 0=>a, 1=>b, etc.

Una vez que la matriz es correcta, la función es trivial.

  • una línea : range('a', 'z')

    – ceder

    13 mayo 2015 a las 14:03

  • @ceadreak Ese rango no satisfará nada de aa y más allá.

    – mickmackusa

    26 ene a las 19:55


Usando la respuesta de Cyril, elaboré un poco para un caso con más de una letra.

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;
}

A continuación se muestran algunos resultados para la función:

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

  • una línea : range('a', 'z')

    – ceder

    13 mayo 2015 a las 14:03

  • @ceadreak Ese rango no satisfará nada de aa y más allá.

    – mickmackusa

    26 ene a las 19:55


Avatar de usuario de Jignesh Joisar
Jignesh Joisar

convertir número a código alfabético

por ejemplo: 1402 a 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);
}

para convertir código alfa a número

por ejemplo: bax a 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;
}

¿Ha sido útil esta solución?