2011-12-22 7 views
5

Tal vez no soy tan bueno en matemáticas, pero estoy teniendo un problema al convertir un número en puro alfabético Bijective Hexavigesimal al igual que lo hace Microsoft Excel/OpenOffice Calc.¿Cómo crear una función que convierta un Número a un Bijetivo Hexavigesimal?

Aquí está una versión de mi código, pero no me dio la salida que necesitaba:

 

    var toHexvg = function(a){ 
    var x=''; 
    var let="_abcdefghijklmnopqrstuvwxyz"; 
    var len=let.length; 
    var b=a; 
    var cnt=0; 
    var y = Array(); 
    do{ 
     a=(a-(a%len))/len; 
     cnt++; 
    }while(a!=0) 
    a=b; 
    var vnt=0; 
    do{ 
     b+=Math.pow((len),vnt)*Math.floor(a/Math.pow((len),vnt+1)); 
     vnt++; 
    }while(vnt!=cnt) 
    var c=b; 
    do{ 
     y.unshift(c%len); 
     c=(c-(c%len))/len; 
    }while(c!=0) 
    for(var i in y)x+=let[y[i]]; 
    return x; 
    } 

La mejor salida de mis esfuerzos pueden conseguir es: a b c d ... y z ba bb bc - aunque no el código real anteriormente. La salida prevista se supone que es a b c ... y z aa ab ac ... zz aaa aab aac ... zzzzz aaaaaa aaaaab, se obtiene la imagen.

Básicamente, mi problema está más en hacer las "matemáticas" que en la función. En definitiva, mi pregunta es: cómo hacer las Matemáticas en conversión Hexavigesimal, hasta un [supuesto] infinito, al igual que Microsoft Excel.

Y si es posible, un código fuente, gracias de antemano.

+1

'aa' no tiene sentido. Es '00'. El "número" después de 'z' es' ba', por lo que su salida parece ser correcta. ¿O es '_' tu' 0', que parece un poco extraño? –

+1

uhm, perdón por el código de muestra, supongo que no debería haberlo publicado, creo que hizo que expresar mi pregunta fuera más complicado, ahaha ... Pero, supongo que mi conclusión es que necesito un código que emita el yz aa ab y no yx ba bb ... Y se podría decir que "_" es el 0, pero la situación que necesito es que ninguna parte de la salida contenga ningún '_'... ^^ hmmm – GheloAce

+0

^[correcciones]: Y se podría decir '\ _' (guión bajo) es el 0, pero la situación que necesito es que ninguna parte del resultado NO contenga ningún '\ _' (guión bajo) ... – GheloAce

Respuesta

10

Bueno, aquí está mi intento, si quiere enviar la secuencia que se inicia con "a" (que representa a 0) y yendo:

a, b, c, ..., y, z, aa, ab, ac, ..., zy, zz, aaa, aab, ... 

Esto funciona y es de esperar tiene algo de sentido La línea de cobarde es allí porque matemáticamente tiene más sentido para 0 a estar representado por la cadena vacía y luego "a" sería 1, etc.

alpha = "abcdefghijklmnopqrstuvwxyz"; 

function hex(a) { 
    // First figure out how many digits there are. 
    a += 1; // This line is funky 
    c = 0; 
    var x = 1;  
    while (a >= x) { 
    c++; 
    a -= x; 
    x *= 26; 
    } 

    // Now you can do normal base conversion. 
    var s = ""; 
    for (var i = 0; i < c; i++) { 
    s = alpha.charAt(a % 26) + s; 
    a = Math.floor(a/26); 
    } 

    return s; 
} 

Sin embargo, si usted está planeando simplemente imprimirlos en orden, hay métodos mucho más eficientes. Por ejemplo, usando recursividad y/o prefijos y demás.

+0

+1 por usar "C++" en tu respuesta. – Jesse

+0

¡Gracias! ^^ ¡Eres increíble ...! Nunca pensé en hacerlo de esa manera ... Muchas gracias ... Estaré poniendo su nombre en los créditos una vez que el sitio esté en funcionamiento, gracias ... - ^^ – GheloAce

+0

Sin preocupaciones, sin necesidad de crédito, el código debe ser compartido y manipulado libremente. Además, user826788 no es muy romántico ... Gracias @Jesse, ¡ni siquiera me di cuenta! – karnok

-2

a representa 0, y z representa 25. Entonces el número después de z es 26, que es 1*26 + 0, entonces ba es correcto. (Y el número después de zzzzz es baaaaa.)

+0

uhm, supongo, pero ¿cómo programarlo para asegurarse de que el próximo a zzz es aaaa ..? Al igual que las columnas en Excel/Calc ..? ^^ – GheloAce

+0

Bueno, no tengo Excel calc Tengo miedo. Sospecho que solo están reduciendo la primera letra por uno. – TonyK

+2

No es tan simple como a = 0 hasta z = 25. El sistema está después de z va a aa. Luego después de zz es aaa. Etc. Así que encontrar el número _nth_ es más complicado que solo una conversión a la base 26 con letras como dígitos. – nnnnnn

0

No entiendo cómo funciona a partir de una fórmula, pero me engañé un rato con él durante un tiempo y se acercó con el siguiente algoritmo para contar, literalmente, hasta el número de columna solicitada:

var getAlpha = (function() { 
    var alphas = [null, "a"], 
     highest = [1]; 

    return function(decNum) { 
     if (alphas[decNum]) 
      return alphas[decNum]; 

     var d, 
      next, 
      carry, 
      i = alphas.length; 

     for(; i <= decNum; i++) { 
      next = ""; 
      carry = true; 
      for(d = 0; d < highest.length; d++){ 
       if (carry) { 
        if (highest[d] === 26) { 
         highest[d] = 1; 
        } else { 
         highest[d]++; 
         carry = false; 
        } 
       } 
       next = String.fromCharCode(
          highest[d] + 96) 
        + next; 
      } 
      if (carry) { 
       highest.push(1); 
       next = "a" + next; 
      } 
      alphas[i] = next; 
     } 

     return alphas[decNum]; 
    }; 
})(); 


alert(getAlpha(27));  // "aa" 
alert(getAlpha(100000)); // "eqxd" 

Demo: http://jsfiddle.net/6SE2f/1/

La matriz highest contiene el número más alto actual con un elemento de matriz por "dígito" (el elemento 0 es el "dígito" menos significativo).

Cuando comencé lo anterior me pareció una buena idea guardar en caché cada valor una vez calculado, para ahorrar tiempo si se solicitaba el mismo valor nuevamente, pero en la práctica (con Chrome) solo tardó unos 3 segundos en calcular el 1,000,000 valor (bdwgn) y aproximadamente 20 segundos para calcular el valor 10,000,000 (uvxxk). Con el almacenamiento en caché eliminado, tomó alrededor de 14 segundos hasta el valor 10,000,000.

3

Aunque @ user826788 ya ha publicado un código de trabajo (que es incluso un tercio más rápido), publicaré mi propio trabajo, que hice antes de encontrar las publicaciones aquí (ya que no sabía la palabra "hexavigesimal"). Sin embargo, también incluye la función al revés.Nótese que uso a = 1, como lo uso para convertir el elemento de la lista de partida desde el

aa) first 
ab) second 

a

<ol type="a" start="27"> 
<li>first</li> 
<li>second</li> 
</ol> 

:

function linum2int(input) { 
    input = input.replace(/[^A-Za-z]/, ''); 
    output = 0; 
    for (i = 0; i < input.length; i++) { 
     output = output * 26 + parseInt(input.substr(i, 1), 26 + 10) - 9; 
    } 
    console.log('linum', output); 
    return output; 
} 

function int2linum(input) { 

    var zeros = 0; 
    var next = input; 
    var generation = 0; 
    while (next >= 27) { 
     next = (next - 1)/26 - (next - 1) % 26/26; 
     zeros += next * Math.pow(27, generation); 
     generation++; 
    } 
    output = (input + zeros).toString(27).replace(/./g, function ($0) { 
     return '_abcdefghijklmnopqrstuvwxyz'.charAt(parseInt($0, 27)); 
    }); 
    return output; 
} 

linum2int("aa"); // 27 
int2linum(27); // "aa" 
+0

Por cierto en firefox el límite superior para' type = "a" 'lista es' 2147483647' o 'fxshrxw';) – jakov

0

Acaba de terminar de escribir this code antes de esta noche, y yo Encontré esta pregunta mientras buscaba qué nombre ponerle a la maldita cosa. Aquí está (en caso de que alguien tenga ganas de usarlo):

/** 
* Convert an integer to bijective hexavigesimal notation (alphabetic base-26). 
* 
* @param {Number} int - A positive integer above zero 
* @return {String} The number's value expressed in uppercased bijective base-26 
*/ 
function bijectiveBase26(int){ 
    const sequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    const length  = sequence.length; 

    if(int <= 0)  return int; 
    if(int <= length) return sequence[int - 1]; 


    let index = (int % length) || length; 
    let result = [sequence[index - 1]]; 

    while((int = Math.floor((int - 1)/length)) > 0){ 
     index = (int % length) || length; 
     result.push(sequence[index - 1]); 
    } 

    return result.reverse().join("") 
} 
Cuestiones relacionadas