2010-11-27 32 views
6

Tengo un número de 128 bits en hexadecimal almacenado en una cadena (de md5, la seguridad no es una preocupación aquí) que me gustaría convertir a una base- 36 cuerdas Si fuera un número de 64 bits o menos, lo convertiría en un entero de 64 bits y luego usaría un algoritmo que encontré para convertir números enteros en cadenas de base 36, pero este número es demasiado grande para eso, así que estoy algo así como una pérdida de cómo abordar esto. Cualquier orientación sería apreciada.Convertir cadena hexadecimal de 128 bits a base-36 cadena

Editar: Después de que Roland Illig señalara la molestia de decir 0/0 y 1/l por teléfono y no obtener mucha densidad de datos por encima del hex, creo que puedo terminar quedándome con hexadecimal. Todavía tengo curiosidad de saber si existe una forma relativamente simple de convertir una cadena hexagonal de longitud arbitraria en una cadena base 36.

Respuesta

6

Una codificación de base 36 requiere 6 bits para almacenar cada token. Igual que base-64 pero no usa 28 de los tokens disponibles. Resolver 36^n> = 2^128 produce n> = log (2^128)/log (36) o 25 tokens para codificar el valor.

Una codificación de base-64 también requiere 6 bits, se utilizan todos los valores token posibles. Resolviendo 64^n> = 2^128 produce n> = log (2^128)/log (64) o 22 tokens para codificar el valor.

Calcular la codificación de la base 36 requiere dividir por potencias de 36. No hay atajos fáciles, se necesita un algoritmo de división que pueda funcionar con valores de 128 bits. La codificación de base 64 es mucho más fácil de calcular ya que es una potencia de 2. Simplemente tome 6 bits a la vez y cambie por 6, en total 22 veces para consumir los 128 bits.

¿Por qué quieres usar base-36? Los codificadores Base-64 son estándar. Si realmente tiene una restricción en el espacio del token (no debería, ASCII rulez), al menos use una codificación base-32. O cualquier potencia de 2, base-16 es hex.

+1

@eco: Si hay una restricción técnica que lo limita a 36 caracteres, entonces puede usar Base-32 en su lugar. Necesitarás usar 26 "dígitos" en lugar de 25, pero puedes usar el cambio de bits. – dan04

+0

La razón para base-36 es que es fácil de leer por teléfono a los humanos. Base-36 me permitiría usar todos los números y el alfabeto, lo que lo haría mucho más corto que solo usar hexadecimal. – eco

+1

base-36 codifica un poco más de 5 bits por dígito, que no es mucho más que los 4 bits que obtienes al usar hexadecimal. El riesgo que está asumiendo es que las personas confunden 0 con O y 1 con I. No creo que valga la pena el esfuerzo.En su lugar, debería utilizar los diez dígitos decimales e imprimirlos en grupos de cuatro. –

1

Si lo único que falta es el apoyo a los enteros sin signo de 128 bits, que aquí es la solución para usted:

#include <stdio.h> 
#include <inttypes.h> 

typedef struct { 
     uint32_t v3, v2, v1, v0; 
} uint128; 

static void 
uint128_divmod(uint128 *out_div, uint32_t *out_mod, const uint128 *in_num, uint32_t in_den) 
{ 
     uint64_t x = 0; 

     x = (x << 32) + in_num->v3; 
     out_div->v3 = x/in_den; 
     x %= in_den; 
     x = (x << 32) + in_num->v2; 
     out_div->v2 = x/in_den; 
     x %= in_den; 
     x = (x << 32) + in_num->v1; 
     out_div->v1 = x/in_den; 
     x %= in_den; 
     x = (x << 32) + in_num->v0; 
     out_div->v0 = x/in_den; 
     x %= in_den; 

     *out_mod = x; 
} 

int 
main(void) 
{ 
     uint128 x = { 0x12345678, 0x12345678, 0x12345678, 0x12345678 }; 
     uint128 result; 
     uint32_t mod; 

     uint128_divmod(&result, &mod, &x, 16); 
     fprintf(stdout, "%08"PRIx32" %08"PRIx32" %08"PRIx32" %08"PRIx32" rest %08"PRIx32"\n", result.v3, result.v2, result.v1, result.v0, mod); 

     return 0; 
} 

Con esta función se puede calcular repetidamente el mod-36 resultado, que le lleva al número codificado como base-36.

1

Dos cosas:
1. Realmente no es tan difícil de dividir una cadena de bytes por 36. Pero si puedes' No se preocupe por implementar eso, puede usar la codificación base-32, que necesitaría 26 bytes en lugar de 25.
2. Si desea poder leer el resultado por teléfono a humanos, debe agregar un simple suma de comprobación a su cadena, que costará uno o dos bytes, pero le ahorrará una gran cantidad de molestias de "susurros chinos" de los clientes con dificultades auditivas.

+0

Hmm, acabo de encontrar este http://www.crockford.com/wrmg/base32.html que aliviaría algunos de los problemas discutidos en otra respuesta. No había considerado una suma de comprobación. Voy a investigar eso. Gracias. – eco

Cuestiones relacionadas