Как преобразовать стандартное целое (в строковом формате) в шестнадцатеричный формат? (С #)
Учитывая потенциально огромное целочисленное значение (в формате строки C#), я хочу иметь возможность генерировать его шестнадцатеричный эквивалент. Обычные методы здесь не применяются, так как мы говорим как угодно большие числа, 50 цифр или более. Техники, которые я видел, которые используют такую технику:
// Store integer 182
int decValue = 182;
// Convert integer 182 as a hex in a string variable
string hexValue = decValue.ToString("X");
// Convert the hex string back to the number
int decAgain = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);
не будет работать, потому что целое число для преобразования слишком велико.
Например, мне нужно иметь возможность преобразовать строку следующим образом:
843370923007003347112437570992242323
в его шестнадцатеричный эквивалент.
это не работает:
C# конвертировать целые числа в шестнадцатеричные и обратно Как преобразовать числа между шестнадцатеричным и десятичным в C#?
4 ответа
О, это просто
var s = "843370923007003347112437570992242323";
var result = new List<byte>();
result.Add( 0 );
foreach ( char c in s )
{
int val = (int)( c - '0' );
for ( int i = 0 ; i < result.Count ; i++ )
{
int digit = result[i] * 10 + val;
result[i] = (byte)( digit & 0x0F );
val = digit >> 4;
}
if ( val != 0 )
result.Add( (byte)val );
}
var hex = "";
foreach ( byte b in result )
hex = "0123456789ABCDEF"[ b ] + hex;
Используйте BigInteger для хранения целого числа, а затем используйте .ToString("X") для этого объекта.
Пример:
var number = BigInteger.Parse("843370923007003347112437570992242323");
string hexValue = number.ToString("X");
Это, однако, ограничено.NET 4 и более поздними версиями. Но Дженс А. указал на класс BigInteger на codeproject, который содержит метод, называемый ToHexString
так что это будет работать для сценария <.NET 4.
Как сказал Дженс, взгляните на реализацию BigInt в Code Project. Даже если у них нет функции для преобразования в шестнадцатеричный код, вы можете легко написать функцию, которая сделает это самостоятельно, если этот BigInt имеет операцию деления и по модулю (я не думаю, что у него есть функция по модулю, так что вы бы также нужно написать по модулю себя)
Хех хорошие решения для dec<->шестнадцатеричных преобразований здесь на stackru до сих пор,... но я нуждался (гигантская int. гигантская фракция) почти без потери точности, поэтому я модифицировал все коды, которые я нашел, с моими уже готовыми кодами, и вот некоторые я могу поделиться (без большого использования int/real lib)
//---------------------------------------------------------------------------
AnsiString str_hex2dec(const AnsiString &hex)
{
char c;
AnsiString dec="",s;
int i,j,l,ll,cy,val;
int i0,i1,i2,i3,sig;
sig=+1; l=hex.Length();
if (l) { c=hex[l]; if (c=='h') l--; if (c=='H') l--; }
i0=0; i1=l; i2=0; i3=l;
for (i=1;i<=l;i++) // scan for parts of number
{
char c=hex[i];
if (c=='-') sig=-sig;
if ((c=='.')||(c==',')) i1=i-1;
if ((c>='0')&&(c<='9')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
if ((c>='A')&&(c<='F')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
if ((c>='a')&&(c<='f')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
}
l=0; s=""; if (i0) for (i=i0;i<=i1;i++)
{
c=hex[i];
if ((c>='0')&&(c<='9')) c-='0';
else if ((c>='A')&&(c<='F')) c-='A'-10;
else if ((c>='a')&&(c<='f')) c-='A'-10;
for (cy=c,j=1;j<=l;j++)
{
val=(s[j]<<4)+cy;
s[j]=val%10;
cy =val/10;
}
while (cy>0)
{
l++;
s+=char(cy%10);
cy/=10;
}
}
if (s!="")
{
for (j=1;j<=l;j++) { c=s[j]; if (c<10) c+='0'; else c+='A'-10; s[j]=c; }
for (i=l,j=1;j<i;j++,i--) { c=s[i]; s[i]=s[j]; s[j]=c; }
dec+=s;
}
if (dec=="") dec="0";
if (sig<0) dec="-"+dec;
if (i2)
{
dec+='.';
s=hex.SubString(i2,i3-i2+1);
l=s.Length();
for (i=1;i<=l;i++)
{
c=s[i];
if ((c>='0')&&(c<='9')) c-='0';
else if ((c>='A')&&(c<='F')) c-='A'-10;
else if ((c>='a')&&(c<='f')) c-='A'-10;
s[i]=c;
}
ll=((l*1234)>>10); // num of decimals to compute
for (cy=0,i=1;i<=ll;i++)
{
for (cy=0,j=l;j>=1;j--)
{
val=s[j];
val*=10;
val+=cy;
s[j]=val&15;
cy=val>>4;
}
dec+=char(cy+'0');
for (;;)
{
if (!l) break;;
if (s[l]) break;
l--;
}
if (!l) break;;
}
}
return dec;
}
//---------------------------------------------------------------------------
AnsiString str_dec2hex(AnsiString dec)
{
AnsiString hex=""; BYTE a,b;
int i,j,i0,i1,i2,i3,l,sig;
sig=+1; l=dec.Length();
i0=0; i1=l; i2=0; i3=l;
for (i=1;i<=l;i++) // scan for parts of number
{
char c=dec[i];
if (c=='-') sig=-sig;
if ((c=='.')||(c==',')) i1=i-1;
if ((c>='0')&&(c<='9')) { if (!i0) i0=i; if ((!i2)&&(i>i1)) i2=i; }
}
if (i0) for (;i1>=i0;i1=j-1)// process integer part /16
{
for (a=0,j=i0,i=i0;i<=i1;i++)
{
a*=10; a+=dec[i]-'0';
if (a<16) { if (j>i0){ dec[j]='0'; j++; } continue; }
b=a>>4; a=a&15;
if (b>10) { dec[j]='1'; j++; b-=10; }
dec[j]=b+'0'; j++;
}
if ((!a)&&(hex=="")) continue;
if (a<10) a+='0'; else a+='A'-10;
hex=AnsiString(char(a))+hex;
}
if (hex=="") hex="0";
if ((i2)&&(i2<=i3)) // process fractional part *16
for (hex+=".",j=i3-i2+2;j;j--)
{
for (a=0,b=0,i=i3;i>=i2;i--)
{
a=dec[i]-'0';
b+=a<<4; dec[i]=(b%10)+'0'; b/=10;
}
if (b<10) b+='0'; else b+='A'-10;
hex+=char(b);
}
if (sig<0) hex="-"+hex; hex+="h";
return hex;
}
//---------------------------------------------------------------------------
PS, если вам нужно отрезать дробные цифры (чтобы отформатировать числа), тогда вам нужно округлить до наиболее значимой цифры вырезанной части.
- округление абс вверх в режиме dec, если цифра>='5'
- округление абс в шестнадцатеричном режиме, если цифра>='8'
если вам интересно, что означает эта строка:
ll=((l*1234)>>10); // num of decimals to compute
чем он вычисляет количество дробных цифр, которые соответствуют точности входной строки (десятичные дробные цифры 1,205 на шестнадцатеричную дробную цифру). Это соотношение я получаю путем эмпирического измерения точности до 1280 бит на дробную часть числа. для простоты 1e-l можно сохранить с максимальной ошибкой до 1e-(l+1). Это соотношение является почти постоянным (за исключением значений младших цифр (<16 цифр), поэтому эту формулу можно безопасно использовать для любого большего числа цифр. При низких значениях входных цифр выводится неверно max на 1 (>8 цифр) или max 2 (<=8 цифр) цифр