PDA

Ver la Versión Completa : Número gigantes a Hexadecimal y visceversa


mightydragonlor
30-08-2011, 22:47:32
Buenas tardes, tengo el siguiente problema, cuando genero un GUID, quitando los guiones y llaves me queda un hexadecimal y requiero convertirlo a un número y de un número igualmente grande requiero convertirlo a hexadecimal, de antemano, muchas gracias.

LoPiTaL
31-08-2011, 11:43:37
Hola.
Puedes usar las funciones BinToHex y HexToBin, que te convierten de arrays de bytes a strings hexadecimales y viceversa respectivamente.

Un saludo,
LoPiTaL

mightydragonlor
31-08-2011, 17:01:04
gracias por responder LoPiTaL, casualmente se me había ocurrido algo por el estilo, pero no encontré algún ejemplo de convertir un string al binario y de binario a hexadecimal, necesitaría convertir esto E80BE67759E943559A65F02FAC6F6E83 a un string de números, y que este string de números lo pueda convertir nuevamente al valor inicial, si sabes de algún link donde expliquen algo parecido te agradeceré mucho, saludos.

LoPiTaL
31-08-2011, 18:42:20
Aquí tienes un link donde muestran un ejemplo de las dos funciones, usando para ello el nº PI con 10 bytes.

http://delphi.about.com/od/beginners/l/blrtlHexToBin.htm

Te presento un código escrito en el navegador sólo como ejemplo.

var
E: array[0..NBytes-1] of Byte;
//Make sure there is room for null terminator
Buf: array[0..NBytes * 2-1] of AnsiChar;
begin
//Debes inicializar Buf para que contenga los caracteres que tú quieres...
Buf[0]:='E';
Buf[1]:='8';
//etc...
HexToBin(Buf, E,NBytes*2-1);
end;

y con eso te lo convertirá de strings a array de bytes.

Si no quieres usar array de AnsiChars, puedes usar también una AnsiString.
Es cuestión de ir probando.

Un saludo,
LoPiTaL

ecfisa
02-09-2011, 04:58:46
Hola mightydragonlor.

Otra opción puede ser:

...
const
B_BIN: array [0..15] of string= ('0000','0001','0010','0011','0100','0101','0110','0111',
'1000','1001','1010','1011','1100','1101','1110','1111');
B_HEX: array [0..15] of char= ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');

function HexadecimalBinario(Value:string):string;
var
i:integer;
begin
for i:= 1 to Length(Value) do
if not (Value[i] in ['0'..'9','A'..'F']) then
raise Exception.Create('Número hexadecimal inválido');
for i:= Length(Value) downto 1 do
Result:= B_BIN[StrToInt('$'+Value[i])] + Result;
end;

function BinarioHexadecimal(Value:string):string;
var
i,n:integer;
Nbl:string;
begin
for i:= 1 to Length(Value) do
if not (Value[i] in ['0','1']) then
raise Exception.Create('Número binario inválido');
Value:= Value + Copy('000', 1, Length(Value) mod 4);
for i:=0 to (Length(Value) shr 2)-1 do
begin
Nbl:= Copy(Value,(i shl 2)+1,4);
n:= 8;
while (Nbl<> B_BIN[n]) do
if Nbl > B_BIN[n] then Inc(n) else Dec(n);
Result:= Result + B_HEX[n];
end;
end;
...


Saludos.

mightydragonlor
10-09-2011, 22:59:05
Hola a todos, no había podido dar repuesta por tanto trabajo, pero les cuento:
un hexadecimal EBD0A0A2B9E5443387C068B6B72699C7 lo convierto a decimal 313451834834061278758346828331453159879 así

{Convierte un hexadecimal en un TBCD}
Function HexToBCD(s : string) : TBcd;
var
bb : Byte;
cc : Char;
begin
Result := 0;
s := UpperCase(s);
for bb := 1 to Length(s) do
begin
Result := Result * 16;
cc := s[bb];
case cc of
'0'..'9': Result:= Result + ord(cc) - ord('0');
'A'..'F': Result:= Result + ord(cc) - ord('A')+10;
else raise EConvertError.Create('Se ha encontrado un caráctar no valido.');
end;
end;
end;

y desde el hexadecimal lo paso a binario 1110101111010000101000001010001010111001111001010100010000110011100001111100000001101000101101101011 0111001001101001100111000111 así

{Convierte un hexadecimal en un binario}
Function HexToBin(Hexadecimal:string):string;
const
BCD: array [0..15] of string=
('0000','0001','0010','0011','0100','0101','0110','0111',
'1000','1001','1010','1011','1100','1101','1110','1111');
var
i:integer;
begin
for i:=Length(Hexadecimal) downto 1 do
Result:=BCD[StrToInt('$'+Hexadecimal[i])]+Result;
end;

desde el binario lo puedo pasar al hexadecimal así

{Convierte un binario a hexadecimal}
function BinToHex(Binario:string):string;
const
BCD: array [0..15] of string=
('0000','0001','0010','0011','0100','0101','0110','0111',
'1000','1001','1010','1011','1100','1101','1110','1111');
HEX: array [0..15] of char=
('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
var
i,n:integer;
sTemp:string;
sNibble:string;
begin
Result:='';
sTemp:=Binario+Copy('000',1,Length(Binario) mod 4);
for i:=0 to (Length(Binario) shr 2)-1 do
begin
sNibble:=Copy(sTemp,(i shl 2)+1,4);
n:=8;
while (sNibble <> BCD[n]) do
if sNibble < BCD[n] then Dec(n) else Inc(n);
Result:=Result+HEX[n];
end;
end;

El gran problema es que desde el décimal no he podido pasarlo a hexadecimal, alguna idea?

ecfisa
11-09-2011, 01:42:13
Hola.

Para convertir una magnitud decimal a hexadecimal no conozco otro que el conocido método de obtener los restos de las sucesivas divisiones por 16.

Usando arítmetica BCD podrías manejar números tales como 313451834834061278758346828331453159879, ya que no estás limitado al número de dígitos.


Un saludo

LoPiTaL
11-09-2011, 13:06:48
Hola.

Para convertir una magnitud decimal a hexadecimal no conozco otro que el conocido método de obtener los restos de las sucesivas divisiones por 16.

Usando arítmetica BCD podrías manejar números tales como 313451834834061278758346828331453159879, ya que no estás limitado al número de dígitos.


Un saludo

Hola, el principal problema de las divisiones por 16 es que te limitará (en enteros) a 32 bits (o 64 si usas int64).
Y el problema de la aritmética BCD, es que el nº que te salga en binario NO es su equivalente decimal, sino, tal como dice el nombre, una representación binaria de éste. Es decir, si realizas la conversión sum(2^(pos-1)) de todos los bits, no te saldría el nº decimal.

Yo no veo solución para convertir números de más de 64 bits a decimal sin recurrir a truquitos como el BCD o así. Si alguien tiene solución, estaría encantado de conocerla.

Un saludo,
LoPiTaL

ecfisa
11-09-2011, 18:40:52
Hola LoPiTal.

Hola, el principal problema de las divisiones por 16 es que te limitará (en enteros) a 32 bits (o 64 si usas int64).

Quizá no me expresé bién, pero hice la mención que no conocía otro método que la obtención de restos no sugiriéndolo, sino por el contrario, descartándolo por la imposibilidad de manejar semejantes números. Así que, totalmente de acuerdo con vos. ;)

En cuanto a obtenerlo manipulando BDC lo sugerí por la cantidad de dígitos que permite, pero realmente no se me ocurre de que modo se podría...

Un saludo.

LoPiTaL
11-09-2011, 23:03:21
Yo pienso que, trabajando con strings, de la misma forma que de hexadecimal a binario, sólo que en lugar de convertir de [$0..$F] en [0000..1111], convertirias [0..9] en [0000..1001]. ¿Eso es BCD no, binary coded decimal? ¿O me estoy liando?
Un saludo,
LoPiTaL

mightydragonlor
12-09-2011, 18:40:41
Alguien tiene algún código para pasar un entero a hexadecimal, que no sea el Format(), si es así os agradecería mucho.

ecfisa
12-09-2011, 18:48:04
Alguien tiene algún código para pasar un entero a hexadecimal, que no sea el Format(), si es así os agradecería mucho.
Hola.

Esa función ya existe en Delphi, y es IntToHex.

Ejemplo de uso:

ShowMessage(IntToHex(65535,4));


Saludos.

mightydragonlor
12-09-2011, 19:25:08
hola ecfisa, gracias por tu respuesta pero no es lo que necesito, necesito mas bien el algoritmo, para poder adaptarlo al TBCD, aunque he buscado bastante en google no he podido encontrar nada xD

ecfisa
12-09-2011, 20:07:55
Hola.

Fijate si te sirve de este modo:

function EnteroAHexadecimal(Num: Int64): string;
const
B16: array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F');
var
Resto: Int64;
begin
Result:= '';
while (Num > 0) do
begin
Resto:= Num mod 16;
Num:= Num div 16;
Result:= B16[Resto] + Result
end;
end;


Ejemplo de llamada:

var
Numero: Int64;
begin
Numero:= 12517;
ShowMessage(EnteroAHexadecimal(Numero));
...


Saludos.

Edito: Pero te vas a topar con la limitante que hablábamos con LoPiTaL más arriba...

mightydragonlor
14-09-2011, 03:57:57
Muchas gracias a todos, les cuento que alfín pude convertir el decimal gigante a hexadecimal, les dejo el código:


{Convierte un TBCD en un hexadecimal}
function BCDToHex(BCD: TBCD): string;
const
B16: array[0..15] of Char = ('0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F');
var
BcdEx,DivBcd: TBCD;
ModInt,SepDec: Integer;
begin
Result:= '';
while (Bcd > 0) do
begin
BCDDivide(Bcd,16,BcdEx);
SepDec:=Pos(DecimalSeparator,BCDToStr(BcdEx))-1;
If SepDec > 0 then begin
DivBcd:=StrToBCD(Copy(BCDToStr(BcdEx),0,SepDec));
end else begin
DivBcd:=BcdEx;
End;
ModInt:=StrToInt(BCDToStr(Bcd - (16 * DivBcd)));
Result:= B16[ModInt] + Result;
BCD:=DivBCD;
end;
end;

Y adicionalmente les dejo el proyecto de ejemplo en Lazarus, está comprimido en 7z así tenga extensión Zip, saludos y muchas gracias.