Eso es, es lo que explica
caricatos. Con su función
binario:
Código PHP:
function binario(x, posi) {
if (posi > 0) return binario(parseInt(x / 2), posi - 1) + (x % 2).toString();
else return (x % 2);
}
Conseguimos pasar un número de decimal a binario con (posi+1) caracteres fijos (rellenando con ceros a la izquierda), entonces convertir una "h" con mi código y con su código devuelven lo mismo, sólo que él rellena de ceros a la izquierda hasta completar (posi+1) posiciones:
Código:
// "h" convertida
01101000 //caricatos
1101000 //derkeNuke
Es lo mismo pero con un cero delante para completar.
Si se devuelve lo mismo al volver a traducir con mi función
toChar no es un motivo de coincidencia. De hecho la función
toChar tiene un bucle principal que hace lo siguiente:
Código:
// cadena a convertir, 01101000:
- cojo desde 0 a 1: "0". Paso de binario a decimal = 0. ¿Esta entre 65 y 122 (letras...)? No, luego coger desde 0 a 2.
- cojo desde 0 a 2: "01". Paso de bin a dec = 1. ¿Es letra? No, luego cogemos (0,3)
- cojo desde 0 a 3: "011". A dec = 3. No es letra.
- cojo (0,4): "0110". dec=6. No es letra.
- cojo (0,5): "01101". dec=13. No es letra.
- cojo (0,6): "011010". dec=26. No es letra.
- cojo (0,7): "0110100". dec=52. No es letra.
- cojo (0,8): "01101000". dec=104. Sí que está en el rango 65-122, luego es letra. ¿Qué letra es 104?, Pues la h. Añadimos una h al resultado.
- como hemos cogido (0,8) y 8 es cadena.length ya no puedo coger más, luego la cadena resultado es "h".
Se comprueba fácilmente cómo 01101000 y 1101000 (sin el 0 inicial) tienen el mismo valor en decimal porque el caracter n de valor a en binario representa en decimal
a*(2^n) (supongo que sabréis pasar de binario a decimal:
011001: 0*(2^5)+1*(2^4)+1*(2^3)+0*(2^2)+0*(2^1)+1*(2^0)=16 +8+1=25 )
Luego al traducir 01101000 y 1101000 da 104 de todas maneras, la letra h.
Lo malo es al concatenar
Código:
h = 01101000 ó 1101000
o = 01101111 ó 1101111
l = 01101100 ó 1101100
a = 01100001 ó 11000011
luego "hola" = 01101000011011110110110001100001 ó 1101000110111111011001100001
Depende si colocamos los ceros para completar el octeto o no.
Pero vamos, que al convertir sería lo mismo.
Personalmente quizás sería mejor la opción de caricatos, y añadiendo un espacio entre octeto y octeto para diferenciar las letras:
Código PHP:
String.prototype.toBase=function(base) {
for(var i=0, dev=""; i<this.length; i++) {
var predev=this.charCodeAt(i).toString(base); //el número en base cambiada
while(predev.length<8) predev="0"+predev; //añadimos tantos ceros a la izquierda como sean necesarios para completar el octeto
dev+= predev+" ";
}
return dev;
}
// "hola" en binario sería "hola".toBase(2) -->
// 01101000 01101111 01101100 01100001
Y al convertirlo de nuevo sería chupado porque no tendríamos que identificar los caracteres:
Código PHP:
String.prototype.toChar=function(fromBase) {
var dev="";
var numeros=this.split(" ");
for(var a=0; a<numeros.length; a++) {
var numDecimal=parseInt( numeros[a], fromBase );
dev+=String.fromCharCode(numDecimal);
}
return dev;
}
Bueno, por fin, código completo para copiar al editor...
Código PHP:
<script language="javascript" type="text/javascript">
function e(q,br) {
document.body.appendChild( document.createTextNode(q) );
if(br!==0) document.body.appendChild( document.createElement("BR") );
}
String.prototype.toBase=function(base) {
for(var i=0, dev=""; i<this.length; i++) {
var predev=this.charCodeAt(i).toString(base); //el número en base cambiada
while(predev.length<8) predev="0"+predev; //añadimos tantos ceros a la izquierda como sean necesarios para completar el octeto
dev+= predev+" ";
}
return dev;
}
String.prototype.toChar=function(fromBase) {
var dev="";
var numeros=this.split(" ");
for(var a=0; a<numeros.length; a++) {
var numDecimal=parseInt( numeros[a], fromBase );
dev+=String.fromCharCode(numDecimal);
}
return dev;
}
var cad="hola";
var base=2;
var conv=cad.toBase(base);
var reConv=conv.toChar(base);
e( cad+" convertido a base "+base+" es "+conv );
e( conv+" reconvertido a caracteres es "+reConv );
</script>
PD: Se me ha ocurrido que podía utilizar expresiones regulares

para traducir de cualquier base a letras:
Código:
String.prototype.toChar=function(fromBase) {
return this.replace(/(([^\s])+\s)/g, function($1) {
return String.fromCharCode( parseInt($1,fromBase) ); //$1 es el grupo que convertiremos
} );
}
Será un poco más rápida la conversión... pero creo que ahí me he ido demasiado... mejor me voy ya a la cama...
PD2: Ojo que en binario el grupo de caracteres es 8, el octeto queda muy bonito. Pero si convertimos a base 36 quedan cosas como 0000002w, que sigue funcionando, pero no se yo hasta qué punto será correcto...
En fin, eso, a dormir ya que las drogas son malas, y odio el javascript.
Un saludo a todos!