BigInteger to Hex / Decimal / Octal / Binary ssortingng?

En Java, je pourrais faire

BigInteger b = new BigInteger(500); 

Puis formatez-le à ma guise

 b.toSsortingng(2); //binary b.toSsortingng(8); //octal b.toSsortingng(10); //decimal b.toSsortingng(16); //hexadecimal 

En C #, je peux faire

 int num = int.Parse(b.ToSsortingng()); Convert.ToSsortingng(num,2) //binary Convert.ToSsortingng(num,8) //octal 

etc. Mais je ne peux le faire qu’avec long valeurs long et plus petites. Existe-t-il une méthode pour imprimer un BigInteger avec une base spécifiée? J’ai posté ceci, BigInteger Parse Octal Ssortingng? , hier et a reçu la solution de la conversion de toutes les chaînes en valeurs BigInteger, sans succès.

    Convertissez BigInteger en BigInteger décimale, hexadécimale, binary, octale:

    Commençons par une valeur BigInteger :

     BigInteger bigint = BigInteger.Parse("123456789012345678901234567890"); 

    Base 10 et Base 16

    Les recouvrements Base 10 (décimal) et base 16 (hexadécimal) intégrés sont faciles:

     // Convert to base 10 (decimal): ssortingng base10 = bigint.ToSsortingng(); // Convert to base 16 (hexadecimal): ssortingng base16 = bigint.ToSsortingng("X"); 

    Zéros à gauche (valeurs BigInteger positives et négatives)

    Notez que ToSsortingng("X") garantit que les chaînes hexadécimales ont un zéro non BigInteger lorsque la valeur de BigInteger est positive. Cela ToSsortingng("X") du comportement habituel de ToSsortingng("X") lors de la conversion à partir d’autres types de valeur où les zéros non significatifs sont supprimés.

    EXEMPLE:

     var positiveBigInt = new BigInteger(128); var negativeBigInt = new BigInteger(-128); Console.WriteLine(positiveBigInt.ToSsortingng("X")); Console.WriteLine(negativeBigInt.ToSsortingng("X")); 

    RÉSULTAT:

     080 80 

    Ce comportement a un objective, car un zéro non BigInteger indique que BigInteger est une valeur positive – le zéro BigInteger indique en BigInteger le signe. Cela est nécessaire (par opposition à d’autres conversions de type valeur) car un BigInteger n’a pas de taille fixe; par conséquent, il n’y a pas de bit de signe désigné. Le zéro non significatif identifie une valeur positive, par opposition à une valeur négative. Cela permet de “contourner” les valeurs BigInteger via ToSsortingng() et de revenir via Parse() . Ce comportement est décrit sur la page BigInteger Structure sur MSDN.

    Méthodes d’extension: BigInteger to Binary, Hex et Octal

    Voici une classe contenant des méthodes d’extension permettant de convertir des instances BigInteger binarys, hexadécimales et octales:

     using System; using System.Numerics; using System.Text; ///  /// Extension methods to convert  /// instances to hexadecimal, octal, and binary ssortingngs. ///  public static class BigIntegerExtensions { ///  /// Converts a  to a binary ssortingng. ///  /// A . ///  /// A  containing a binary /// representation of the supplied . ///  public static ssortingng ToBinarySsortingng(this BigInteger bigint) { var bytes = bigint.ToByteArray(); var idx = bytes.Length - 1; // Create a SsortingngBuilder having appropriate capacity. var base2 = new SsortingngBuilder(bytes.Length * 8); // Convert first byte to binary. var binary = Convert.ToSsortingng(bytes[idx], 2); // Ensure leading zero exists if value is positive. if (binary[0] != '0' && bigint.Sign == 1) { base2.Append('0'); } // Append binary ssortingng to SsortingngBuilder. base2.Append(binary); // Convert remaining bytes adding leading zeros. for (idx--; idx >= 0; idx--) { base2.Append(Convert.ToSsortingng(bytes[idx], 2).PadLeft(8, '0')); } return base2.ToSsortingng(); } ///  /// Converts a  to a hexadecimal ssortingng. ///  /// A . ///  /// A  containing a hexadecimal /// representation of the supplied . ///  public static ssortingng ToHexadecimalSsortingng(this BigInteger bigint) { return bigint.ToSsortingng("X"); } ///  /// Converts a  to a octal ssortingng. ///  /// A . ///  /// A  containing an octal /// representation of the supplied . ///  public static ssortingng ToOctalSsortingng(this BigInteger bigint) { var bytes = bigint.ToByteArray(); var idx = bytes.Length - 1; // Create a SsortingngBuilder having appropriate capacity. var base8 = new SsortingngBuilder(((bytes.Length / 3) + 1) * 8); // Calculate how many bytes are extra when byte array is split // into three-byte (24-bit) chunks. var extra = bytes.Length % 3; // If no bytes are extra, use three bytes for first chunk. if (extra == 0) { extra = 3; } // Convert first chunk (24-bits) to integer value. int int24 = 0; for (; extra != 0; extra--) { int24 <<= 8; int24 += bytes[idx--]; } // Convert 24-bit integer to octal without adding leading zeros. var octal = Convert.ToString(int24, 8); // Ensure leading zero exists if value is positive. if (octal[0] != '0' && bigint.Sign == 1) { base8.Append('0'); } // Append first converted chunk to StringBuilder. base8.Append(octal); // Convert remaining 24-bit chunks, adding leading zeros. for (; idx >= 0; idx -= 3) { int24 = (bytes[idx] << 16) + (bytes[idx - 1] << 8) + bytes[idx - 2]; base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0')); } return base8.ToString(); } } 

    À première vue, ces méthodes peuvent sembler plus complexes que nécessaire. En effet, un peu de complexité supplémentaire est ajoutée pour garantir la présence des zéros non significatifs dans les chaînes converties.

    Examinons chaque méthode d'extension pour voir comment elle fonctionne:

    BigInteger.ToBinarySsortingng ()

    Voici comment utiliser cette méthode d'extension pour convertir un BigInteger en chaîne binary:

     // Convert BigInteger to binary ssortingng. bigint.ToBinarySsortingng(); 

    Le kernel fondamental de chacune de ces méthodes d'extension est la méthode BigInteger.ToByteArray() . Cette méthode convertit un BigInteger en un tableau d'octets, ce qui nous permet d'obtenir la représentation binary d'une valeur BigInteger :

     var bytes = bigint.ToByteArray(); 

    Attention, cependant, le tableau d'octets renvoyé est dans un ordre little-endian. Le premier élément de tableau est donc l'octet le moins significatif (LSB) de BigInteger . Dans la mesure où SsortingngBuilder est utilisé pour créer la chaîne de sortie, qui commence au chiffre le plus significatif (MSB), le tableau d'octets doit être itéré en sens inverse pour que l'octet le plus significatif soit d'abord converti.

    Ainsi, un pointeur d'index est défini sur le chiffre le plus significatif (le dernier élément) dans le tableau d'octets:

     var idx = bytes.Length - 1; 

    Pour capturer les octets convertis, un SsortingngBuilder est créé:

     var base2 = new SsortingngBuilder(bytes.Length * 8); 

    Le constructeur SsortingngBuilder prend la capacité pour SsortingngBuilder . La capacité nécessaire pour SsortingngBuilder est calculée en prenant le nombre d'octets à convertir multiplié par huit (huit chiffres binarys résultent de chaque octet converti).

    Le premier octet est ensuite converti en une chaîne binary:

     var binary = Convert.ToSsortingng(bytes[idx], 2); 

    À ce stade, il est nécessaire de s'assurer qu'il existe un zéro non BigInteger si BigInteger est une valeur positive (voir la discussion ci-dessus). Si le premier chiffre converti n'est pas un zéro et que bigint est positif, un '0' est ajouté au SsortingngBuilder :

     // Ensure leading zero exists if value is positive. if (binary[0] != '0' && bigint.Sign == 1) { base2.Append('0'); } 

    Ensuite, l'octet converti est ajouté au SsortingngBuilder :

     base2.Append(binary); 

    Pour convertir les octets restants, une boucle itère le rest du tableau d'octets dans l'ordre inverse:

     for (idx--; idx >= 0; idx--) { base16.Append(Convert.ToSsortingng(bytes[idx], 2).PadLeft(8, '0')); } 

    Notez que chaque octet converti est complété à gauche par des zéros ('0'), si nécessaire, de sorte que la chaîne convertie comporte huit caractères binarys. C'est extrêmement important. Sans ce remplissage, la valeur hexadécimale '101' serait convertie en une valeur binary de '11'. Les zéros à gauche assurent que la conversion est '100000001'.

    Lorsque tous les octets sont convertis, SsortingngBuilder contient la chaîne binary complète, qui est renvoyée par la méthode d'extension:

     return base2.ToSsortingng(); 

    BigInteger.ToOctalSsortingng

    Convertir un BigInteger en BigInteger octale (base 8) est plus compliqué. Le problème est que les chiffres octaux représentent trois bits, ce qui n’est pas un multiple pair des huit bits BigInteger.ToByteArray() dans chaque élément du tableau d’octets créé par BigInteger.ToByteArray() . Pour résoudre ce problème, trois octets du tableau sont combinés en morceaux de 24 bits. Chaque bloc de 24 bits est converti uniformément en huit caractères octaux.

    Le premier bloc de 24 bits nécessite des calculs modulo:

     var extra = bytes.Length % 3; 

    Ce calcul détermine le nombre d'octets "supplémentaires" lorsque l'ensemble du tableau d'octets est divisé en blocs de trois octets (24 bits). La première conversion en octal (les chiffres les plus significatifs) obtient les octets "supplémentaires", de sorte que toutes les conversions restantes obtiennent chacune trois octets.

    S'il n'y a pas d'octets "extra", alors le premier morceau aura trois octets complets:

     if (extra == 0) { extra = 3; } 

    Le premier bloc est chargé dans une variable entière appelée int24 pouvant contenir jusqu'à 24 bits. Chaque octet du morceau est chargé. Lorsque des octets supplémentaires sont chargés, les bits précédents de int24 sont int24 gauche de 8 bits pour int24 espace:

     int int24 = 0; for (; extra != 0; extra--) { int24 <<= 8; int24 += bytes[idx--]; } 

    La conversion d'un bloc de 24 bits en octal est réalisée par:

     var octal = Convert.ToSsortingng(int24, 8); 

    Encore une fois, le premier chiffre doit être un zéro si le BigInteger est une valeur positive:

     // Ensure leading zero exists if value is positive. if (octal[0] != '0' && bigint.Sign == 1) { base8.Append('0'); } 

    Le premier morceau converti est ajouté au SsortingngBuilder :

     base8.Append(octal); 

    Les morceaux de 24 bits restants sont convertis en boucle:

     for (; idx >= 0; idx -= 3) { int24 = (bytes[idx] << 16) + (bytes[idx -1] << 8) + bytes[idx - 2]; base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0')); } 

    Comme pour la conversion binary, chaque chaîne octale convertie est complétée à gauche par des zéros, de sorte que "7" devienne "00000007". Cela garantit que les zéros ne seront pas supprimés du milieu des chaînes converties (c'est-à-dire «17» au lieu de «100000007»).

    Conversion en base x?

    La conversion d'un BigInteger d'autres bases de nombres pourrait être beaucoup plus compliquée. Tant que la base numérique est une puissance de deux (c'est-à-dire 2, 4, 8, 16), le tableau d'octets créé par BigInteger.ToByteArray() peut être fractionné de manière appropriée en blocs de bits et converti.

    Cependant, si la base de nombres n’est pas une puissance de deux, le problème devient beaucoup plus compliqué et nécessite beaucoup de bouclage et de division. Comme ces conversions de bases de numéros sont rares, je n’ai couvert ici que les bases de calcul populaires.

    Après une longue journée de travail avec BigInteger, j’ai eu une meilleure façon de faire la sortie de la chaîne en binary, essayez ceci! (fonctionne pour les nombres négatifs)

     // Important note: when parsing hexadecimal ssortingng, make sure to prefix // with 0 if the number is positive. Ex: 0F instead of F, and 01A3 instead of 1A3. // If the number is negative, then the first bit should be set to 1. var x = BigInteger.Parse("0F", NumberStyles.HexNumber); // Or: BigInteger.Parse("15") var biBytes = x.ToByteArray(); var bits = new bool [8 * biBytes.Length]; new BitArray(x.ToByteArray()).CopyTo(bits, 0); bits = bits.Reverse().ToArray(); // BigInteger uses little endian when extracting bytes (thus bits), so we inverse them. var builder = new SsortingngBuilder(); foreach(var bit in bits) { builder.Append(bit ? '1' : '0'); } ssortingng final = Regex.Replace(builder.ToSsortingng(), @"^0+", ""); // Because bytes consume full 8 bits, we might occasionally get leading zeros. Console.WriteLine(final); 

    Sortie: 1111

    C’est une méthode simple pour convertir un BigInteger en n’importe quelle base:

     public static ssortingng ToNBase(BigInteger a, int n) { SsortingngBuilder sb = new SsortingngBuilder(); while (a > 0) { sb.Insert(0,a % n); a /= n; } return sb.ToSsortingng(); } 

    Cela fonctionne parfaitement pour la base 2-10. Si vous voulez qu’il produise des chaînes hexadécimales ou d’autres chaînes de base plus élevées, vous devez modifier a % b fonction de la base avant de l’insérer.