Le moyen le plus rapide de convertir un numéro de base 10 en n’importe quelle base dans .NET?

J’ai et vieux (ish) C # méthode j’ai écrit qui prend un nombre et le convertit en n’importe quelle base:

ssortingng ConvertToBase(int number, char[] baseChars); 

Ce n’est pas si rapide et soigné. Existe-t-il un bon moyen connu d’atteindre cet objective dans .NET?

Je cherche quelque chose qui me permet d’utiliser n’importe quelle base avec une chaîne de caractères arbitraire à utiliser.

Cela ne permet que les bases 16, 10, 8 et 2:

 Convert.ToSsortingng(1, x); 

Je veux l’utiliser pour obtenir une base extrêmement élevée en tirant parti des chiffres, de toutes les minuscules et de toutes les majuscules. Comme dans ce fil , mais pour C # pas JavaScript.

Est-ce que quelqu’un connait un moyen efficace de le faire en C #?

Convert.ToSsortingng peut être utilisé pour convertir un nombre à sa représentation sous forme de chaîne équivalente dans une base spécifiée.

Exemple:

 ssortingng binary = Convert.ToSsortingng(5, 2); // convert 5 to its binary representation Console.WriteLine(binary); // prints 101 

Cependant, comme le soulignent les commentaires, Convert.ToSsortingng ne prend en charge que le jeu de bases suivant limité, mais généralement suffisant: 2, 8, 10 ou 16.

Mise à jour (pour satisfaire à l’exigence de conversion vers n’importe quelle base):

Je ne connais aucune méthode dans la BCL qui soit capable de convertir des nombres en n’importe quelle base, vous devrez donc écrire votre propre petite fonction utilitaire. Un exemple simple ressemblerait à ceci (notez que cela peut sûrement être fait plus rapidement en remplaçant la concaténation de chaîne):

 class Program { static void Main(ssortingng[] args) { // convert to binary ssortingng binary = IntToSsortingng(42, new char[] { '0', '1' }); // convert to hexadecimal ssortingng hex = IntToSsortingng(42, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}); // convert to hexavigesimal (base 26, AZ) ssortingng hexavigesimal = IntToSsortingng(42, Enumerable.Range('A', 26).Select(x => (char)x).ToArray()); // convert to sexagesimal ssortingng xx = IntToSsortingng(42, new char[] { '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x'}); } public static ssortingng IntToSsortingng(int value, char[] baseChars) { ssortingng result = ssortingng.Empty; int targetBase = baseChars.Length; do { result = baseChars[value % targetBase] + result; value = value / targetBase; } while (value > 0); return result; } ///  /// An optimized method using an array as buffer instead of /// ssortingng concatenation. This is faster for return values having /// a length > 1. ///  public static ssortingng IntToSsortingngFast(int value, char[] baseChars) { // 32 is the worst cast buffer size for base 2 and int.MaxValue int i = 32; char[] buffer = new char[i]; int targetBase= baseChars.Length; do { buffer[--i] = baseChars[value % targetBase]; value = value / targetBase; } while (value > 0); char[] result = new char[32 - i]; Array.Copy(buffer, i, result, 0, 32 - i); return new ssortingng(result); } } 

Mise à jour 2 (Amélioration de la performance)

L’utilisation d’un tampon de tableau au lieu d’une concaténation de chaînes pour générer la chaîne de résultat améliore les performances, en particulier sur les grands nombres (voir la méthode IntToSsortingngFast ). Dans le meilleur des cas (c’est-à-dire l’entrée la plus longue possible), cette méthode est environ trois fois plus rapide. Cependant, pour les nombres à 1 chiffre (1 chiffre dans la base cible), IntToSsortingng sera plus rapide.

J’ai récemment blogué à ce sujet . Mon implémentation n’utilise aucune opération de chaîne lors des calculs, ce qui la rend très rapide . La conversion vers un système numérique avec une base de 2 à 36 est prise en charge:

 ///  /// Converts the given decimal number to the numeral system with the /// specified radix (in the range [2, 36]). ///  /// The number to convert. /// The radix of the destination numeral system (in the range [2, 36]). ///  public static ssortingng DecimalToArbitrarySystem(long decimalNumber, int radix) { const int BitsInLong = 64; const ssortingng Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (radix < 2 || radix > Digits.Length) throw new ArgumentException("The radix must be >= 2 and <= " + Digits.Length.ToString()); if (decimalNumber == 0) return "0"; int index = BitsInLong - 1; long currentNumber = Math.Abs(decimalNumber); char[] charArray = new char[BitsInLong]; while (currentNumber != 0) { int remainder = (int)(currentNumber % radix); charArray[index--] = Digits[remainder]; currentNumber = currentNumber / radix; } string result = new String(charArray, index + 1, BitsInLong - index - 1); if (decimalNumber < 0) { result = "-" + result; } return result; } 

J'ai également implémenté une fonction inverse rapide au cas où quelqu'un en aurait besoin: Système de nombres arbitraire à décimal .

On peut aussi utiliser une version légèrement modifiée de celle acceptée et ajuster la chaîne de caractères de base à ses besoins:

 public static ssortingng Int32ToSsortingng(int value, int toBase) { ssortingng result = ssortingng.Empty; do { result = "0123456789ABCDEF"[value % toBase] + result; value /= toBase; } while (value > 0); return result; } 

Très tard pour la fête sur celui-ci, mais j’ai écrit le cours d’aide suivant pour un projet au travail. Il a été conçu pour convertir des chaînes courtes en nombres et inversement (une fonction simplifiée de hachage parfait ), mais il effectuera également la conversion de nombres entre des bases arbitraires. L’ Base10ToSsortingng méthode Base10ToSsortingng répond à la question initialement publiée.

L’indicateur shouldSupportRoundTripping transmis au constructeur de classe est nécessaire pour empêcher la perte de chiffres en tête de la chaîne de numéros lors de la conversion en base 10 et inversement (crucial, compte tenu de mes exigences!). La plupart du temps, la perte des principaux 0 de la chaîne numérique ne sera probablement pas un problème.

En tout cas, voici le code:

 using System; using System.Collections.Generic; using System.Linq; namespace StackOverflow { ///  /// Contains methods used to convert numbers between base-10 and another numbering system. ///  ///  ///  /// This conversion class makes use of a set of characters that represent the digits used by the target /// numbering system. For example, binary would use the digits 0 and 1, whereas hex would use the digits /// 0 through 9 plus A through F. The digits do not have to be numerals. ///  ///  /// The first digit in the sequence has special significance. If the number passed to the ///  method has leading digits that match the first digit, then those leading /// digits will effectively be 'lost' during conversion. Much of the time this won't matter. For example, /// "0F" hex will be converted to 15 decimal, but when converted back to hex it will become simply "F", /// losing the leading "0". However, if the set of digits was A through Z, and the number "ABC" was /// converted to base-10 and back again, then the leading "A" would be lost. The  /// flag passed to the constructor allows 'round-sortingpping' behaviour to be supported, which will prevent /// leading digits from being lost during conversion. ///  ///  /// Note that numeric overflow is probable when using longer ssortingngs and larger digit sets. ///  ///  public class Base10Converter { const char NullDigit = '\0'; public Base10Converter(ssortingng digits, bool shouldSupportRoundTripping = false) : this(digits.ToCharArray(), shouldSupportRoundTripping) { } public Base10Converter(IEnumerable digits, bool shouldSupportRoundTripping = false) { if (digits == null) { throw new ArgumentNullException("digits"); } if (digits.Count() == 0) { throw new ArgumentException( message: "The sequence is empty.", paramName: "digits" ); } if (!digits.Distinct().SequenceEqual(digits)) { throw new ArgumentException( message: "There are duplicate characters in the sequence.", paramName: "digits" ); } if (shouldSupportRoundTripping) { digits = (new[] { NullDigit }).Concat(digits); } _digitToIndexMap = digits .Select((digit, index) => new { digit, index }) .ToDictionary(keySelector: x => x.digit, elementSelector: x => x.index); _radix = _digitToIndexMap.Count; _indexToDigitMap = _digitToIndexMap .ToDictionary(keySelector: x => x.Value, elementSelector: x => x.Key); } readonly Dictionary _digitToIndexMap; readonly Dictionary _indexToDigitMap; readonly int _radix; public long SsortingngToBase10(ssortingng number) { Func selector = (c, i) => { int power = number.Length - i - 1; int digitIndex; if (!_digitToIndexMap.TryGetValue(c, out digitIndex)) { throw new ArgumentException( message: Ssortingng.Format("Number contains an invalid digit '{0}' at position {1}.", c, i), paramName: "number" ); } return Convert.ToInt64(digitIndex * Math.Pow(_radix, power)); }; return number.Select(selector).Sum(); } public ssortingng Base10ToSsortingng(long number) { if (number < 0) { throw new ArgumentOutOfRangeException( message: "Value cannot be negative.", paramName: "number" ); } string text = string.Empty; long remainder; do { number = Math.DivRem(number, _radix, out remainder); char digit; if (!_indexToDigitMap.TryGetValue((int) remainder, out digit) || digit == NullDigit) { throw new ArgumentException( message: "Value cannot be converted given the set of digits used by this converter.", paramName: "number" ); } text = digit + text; } while (number > 0); return text; } } } 

Cela peut également être sous-classé pour dériver des convertisseurs de nombres personnalisés:

 namespace StackOverflow { public sealed class BinaryNumberConverter : Base10Converter { public BinaryNumberConverter() : base(digits: "01", shouldSupportRoundTripping: false) { } } public sealed class HexNumberConverter : Base10Converter { public HexNumberConverter() : base(digits: "0123456789ABCDEF", shouldSupportRoundTripping: false) { } } } 

Et le code serait utilisé comme ceci:

 using System.Diagnostics; namespace StackOverflow { class Program { static void Main(ssortingng[] args) { { var converter = new Base10Converter( digits: "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz", shouldSupportRoundTripping: true ); long number = converter.SsortingngToBase10("Atoz"); ssortingng text = converter.Base10ToSsortingng(number); Debug.Assert(text == "Atoz"); } { var converter = new HexNumberConverter(); ssortingng text = converter.Base10ToSsortingng(255); long number = converter.SsortingngToBase10(text); Debug.Assert(number == 255); } } } } 

MÉTHODES RAPIDES ” DE ” ET ” À

Je suis en retard à la fête, mais j’ai ajouté des réponses précédentes et je les ai améliorées. Je pense que ces deux méthodes sont plus rapides que toutes les autres affichées jusqu’ici. J’ai été capable de convertir 1 000 000 de numéros de et vers la base 36 en moins de 400 ms dans une machine à cœur unique.

L’exemple ci-dessous concerne la base 62 . Modifiez le tableau BaseChars à convertir depuis et vers toute autre base.

 private static readonly char[] BaseChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray(); private static readonly Dictionary CharValues = BaseChars .Select((c,i)=>new {Char=c, Index=i}) .ToDictionary(c=>c.Char,c=>c.Index); public static ssortingng LongToBase(long value) { long targetBase = BaseChars.Length; // Determine exact number of characters to use. char[] buffer = new char[Math.Max( (int) Math.Ceiling(Math.Log(value + 1, targetBase)), 1)]; var i = buffer.Length; do { buffer[--i] = BaseChars[value % targetBase]; value = value / targetBase; } while (value > 0); return new ssortingng(buffer, i, buffer.Length - i); } public static long BaseToLong(ssortingng number) { char[] chrs = number.ToCharArray(); int m = chrs.Length - 1; int n = BaseChars.Length, x; long result = 0; for (int i = 0; i < chrs.Length; i++) { x = CharValues[ chrs[i] ]; result += x * (long)Math.Pow(n, m--); } return result; } 

EDIT (2018-07-12)

Correction de l'adresse du coin trouvé par @AdrianBotor (voir commentaires) en convertissant 46655 en base 36. Ceci est dû à une erreur de calcul en virgule flottante qui calcule Math.Log(46656, 36) exactement 3, mais .NET renvoie 3 + 4.44e-16 , ce qui crée un caractère supplémentaire dans le tampon de sortie.

Cette classe de ce forum pourrait-elle vous aider?

 public class BaseConverter { public static ssortingng ToBase(ssortingng number, int start_base, int target_base) { int base10 = this.ToBase10(number, start_base); ssortingng rtn = this.FromBase10(base10, target_base); return rtn; } public static int ToBase10(ssortingng number, int start_base) { if (start_base < 2 || start_base > 36) return 0; if (start_base == 10) return Convert.ToInt32(number); char[] chrs = number.ToCharArray(); int m = chrs.Length - 1; int n = start_base; int x; int rtn = 0; foreach(char c in chrs) { if (char.IsNumber(c)) x = int.Parse(c.ToSsortingng()); else x = Convert.ToInt32(c) - 55; rtn += x * (Convert.ToInt32(Math.Pow(n, m))); m--; } return rtn; } public static ssortingng FromBase10(int number, int target_base) { if (target_base < 2 || target_base > 36) return ""; if (target_base == 10) return number.ToSsortingng(); int n = target_base; int q = number; int r; ssortingng rtn = ""; while (q >= n) { r = q % n; q = q / n; if (r < 10) rtn = r.ToString() + rtn; else rtn = Convert.ToChar(r + 55).ToString() + rtn; } if (q < 10) rtn = q.ToString() + rtn; else rtn = Convert.ToChar(q + 55).ToString() + rtn; return rtn; } } 

Totalement non testé ... faites le moi savoir si ça marche! (Copié-collé dans le cas où le post du forum disparaît ou quelque chose ...)

Moi aussi, je cherchais un moyen rapide de convertir le nombre décimal en une autre base dans la plage de [2..36]. J’ai donc développé le code suivant. Son simple à suivre et utilise un object Ssortingngbuilder comme proxy pour un tampon de caractères que nous pouvons indexer caractère par caractère. Le code semble être très rapide comparé aux alternatives et beaucoup plus rapide que l’initialisation des caractères individuels dans un tableau de caractères.

Pour votre propre usage, vous pouvez préférer: 1 / Renvoyer une chaîne vide plutôt que de lancer une exception. 2 / Supprimez la vérification de la base pour que la méthode s’exécute encore plus rapidement. 3 / Initialisez l’object Ssortingngbuilder avec 32 ‘0 et supprimez le résultat de la ligne. Retirez (0, i) ;. Cela provoquera le retour de la chaîne avec des zéros non significatifs et augmentera encore la vitesse. 4 / Faites de l’object Ssortingngbuilder un champ statique dans la classe afin que, quel que soit le nombre de fois que la méthode DecimalToBase est appelée, l’object Ssortingngbuilder n’est initialisé qu’une fois. Si vous faites ce changement 3 ci-dessus ne fonctionnerait plus.

J’espère que quelqu’un trouve cela utile 🙂

AtomicParadox

  static ssortingng DecimalToBase(int number, int radix) { // Check that the radix is between 2 and 36 inclusive if ( radix < 2 || radix > 36 ) throw new ArgumentException("ConvertToBase(int number, int radix) - Radix must be between 2 and 36."); // Create a buffer large enough to hold the largest int value represented in binary digits SsortingngBuilder result = new SsortingngBuilder(" "); // 32 spaces // The base conversion calculates the digits in reverse order so use // an index to point to the last unused space in our buffer int i = 32; // Convert the number to the new base do { int remainder = number % radix; number = number / radix; if(remainder <= 9) result[--i] = (char)(remainder + '0'); // Converts [0..9] to ASCII ['0'..'9'] else result[--i] = (char)(remainder + '7'); // Converts [10..36] to ASCII ['A'..'Z'] } while ( number > 0 ); // Remove the unwanted padding from the front of our buffer and return the result // Note i points to the last unused character in our buffer result.Remove( 0, i ); return (result.ToSsortingng()); } 

Je l’utilisais pour stocker un Guid comme une chaîne plus courte (mais était limité à utiliser 106 caractères). Si quelqu’un est intéressé, voici mon code pour le décodage de la chaîne en valeur numérique (dans ce cas, j’ai utilisé 2 ulongs pour la valeur Guid, plutôt que de coder un Int128 (puisque je ne suis pas en 3.5 pas 4.0). chaîne const avec 106 caractères uniques. ConvertLongsToBytes est assez peu excitant.

 private static Guid B106ToGuid(ssortingng pStr) { try { ulong tMutl = 1, tL1 = 0, tL2 = 0, targetBase = (ulong)CODE.Length; for (int i = 0; i < pStr.Length / 2; i++) { tL1 += (ulong)CODE.IndexOf(pStr[i]) * tMutl; tL2 += (ulong)CODE.IndexOf(pStr[pStr.Length / 2 + i]) * tMutl; tMutl *= targetBase; } return new Guid(ConvertLongsToBytes(tL1, tL2)); } catch (Exception ex) { throw new Exception("B106ToGuid failed to convert string to Guid", ex); } } 

J’avais un besoin similaire, sauf que je devais aussi faire des maths sur les “nombres”. J’ai pris certaines des suggestions ici et créé une classe qui fera tout ce truc amusant. Cela permet d’utiliser n’importe quel caractère Unicode pour représenter un nombre et cela fonctionne aussi avec des décimales.

Cette classe est assez facile à utiliser. Créez simplement un nombre comme type de New BaseNumber , définissez quelques propriétés et désactivez-le. Les routines veillent à basculer automatiquement entre la base 10 et la base x et la valeur que vous définissez est conservée dans la base dans laquelle vous l’avez définie, donc aucune précision n’est perdue (jusqu’à la conversion, mais la perte de précision devrait être minime la routine utilise Double et Long si possible).

Je ne peux pas commander la vitesse de cette routine. C’est probablement assez lent, donc je ne suis pas sûr que cela convienne aux besoins de celui qui a posé la question, mais il est certain que c’est flexible, alors j’espère que quelqu’un d’autre pourra l’utiliser.

Pour quiconque ayant besoin de ce code pour calculer la colonne suivante dans Excel, je vais inclure le code de boucle que j’ai utilisé et qui tire parti de cette classe.

 Public Class BaseNumber Private _CharacterArray As List(Of Char) Private _BaseXNumber As Ssortingng Private _Base10Number As Double? Private NumberBaseLow As Integer Private NumberBaseHigh As Integer Private DecimalSeparator As Char = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator Private GroupSeparator As Char = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator Public Sub UseCapsLetters() 'http://unicodelookup.com TrySetBaseSet(65, 90) End Sub Public Function GetCharacterArray() As List(Of Char) Return _CharacterArray End Function Public Sub SetCharacterArray(CharacterArray As Ssortingng) _CharacterArray = New List(Of Char) _CharacterArray.AddRange(CharacterArray.ToList) TrySetBaseSet(_CharacterArray) End Sub Public Sub SetCharacterArray(CharacterArray As List(Of Char)) _CharacterArray = CharacterArray TrySetBaseSet(_CharacterArray) End Sub Public Sub SetNumber(Value As Ssortingng) _BaseXNumber = Value _Base10Number = Nothing End Sub Public Sub SetNumber(Value As Double) _Base10Number = Value _BaseXNumber = Nothing End Sub Public Function GetBaseXNumber() As Ssortingng If _BaseXNumber IsNot Nothing Then Return _BaseXNumber Else Return ToBaseSsortingng() End If End Function Public Function GetBase10Number() As Double If _Base10Number IsNot Nothing Then Return _Base10Number Else Return ToBase10() End If End Function Private Sub TrySetBaseSet(Values As List(Of Char)) For Each value As Char In _BaseXNumber If Not Values.Contains(value) Then Throw New ArgumentOutOfRangeException("The ssortingng has a value, " & value & ", not contained in the selected 'base' set.") _CharacterArray.Clear() DetermineNumberBase() End If Next _CharacterArray = Values End Sub Private Sub TrySetBaseSet(LowValue As Integer, HighValue As Integer) Dim HighLow As KeyValuePair(Of Integer, Integer) = GetHighLow() If HighLow.Key < LowValue OrElse HighLow.Value > HighValue Then Throw New ArgumentOutOfRangeException("The ssortingng has a value not contained in the selected 'base' set.") _CharacterArray.Clear() DetermineNumberBase() End If NumberBaseLow = LowValue NumberBaseHigh = HighValue End Sub Private Function GetHighLow(Optional Values As List(Of Char) = Nothing) As KeyValuePair(Of Integer, Integer) If Values Is Nothing Then Values = _BaseXNumber.ToList End If Dim lowestValue As Integer = Convert.ToInt32(Values(0)) Dim highestValue As Integer = Convert.ToInt32(Values(0)) Dim currentValue As Integer For Each value As Char In Values If value <> DecimalSeparator AndAlso value <> GroupSeparator Then currentValue = Convert.ToInt32(value) If currentValue > highestValue Then highestValue = currentValue End If If currentValue < lowestValue Then currentValue = lowestValue End If End If Next Return New KeyValuePair(Of Integer, Integer)(lowestValue, highestValue) End Function Public Sub New(BaseXNumber As String) _BaseXNumber = BaseXNumber DetermineNumberBase() End Sub Public Sub New(BaseXNumber As String, NumberBase As Integer) Me.New(BaseXNumber, Convert.ToInt32("0"c), NumberBase) End Sub Public Sub New(BaseXNumber As String, NumberBaseLow As Integer, NumberBaseHigh As Integer) _BaseXNumber = BaseXNumber Me.NumberBaseLow = NumberBaseLow Me.NumberBaseHigh = NumberBaseHigh End Sub Public Sub New(Base10Number As Double) _Base10Number = Base10Number End Sub Private Sub DetermineNumberBase() Dim highestValue As Integer Dim currentValue As Integer For Each value As Char In _BaseXNumber currentValue = Convert.ToInt32(value) If currentValue > highestValue Then highestValue = currentValue End If Next NumberBaseHigh = highestValue NumberBaseLow = Convert.ToInt32("0"c) 'assume 0 is the lowest End Sub Private Function ToBaseSsortingng() As Ssortingng Dim Base10Number As Double = _Base10Number Dim intPart As Long = Math.Truncate(Base10Number) Dim fracPart As Long = (Base10Number - intPart).ToSsortingng.Replace(DecimalSeparator, "") Dim intPartSsortingng As Ssortingng = ConvertIntToSsortingng(intPart) Dim fracPartSsortingng As Ssortingng = If(fracPart <> 0, DecimalSeparator & ConvertIntToString(fracPart), "") Return intPartString & fracPartString End Function Private Function ToBase10() As Double Dim intPartString As String = _BaseXNumber.Split(DecimalSeparator)(0).Replace(GroupSeparator, "") Dim fracPartString As String = If(_BaseXNumber.Contains(DecimalSeparator), _BaseXNumber.Split(DecimalSeparator)(1), "") Dim intPart As Long = ConvertStringToInt(intPartString) Dim fracPartNumerator As Long = ConvertStringToInt(fracPartString) Dim fracPartDenominator As Long = ConvertStringToInt(GetEncodedChar(1) & String.Join("", Enumerable.Repeat(GetEncodedChar(0), fracPartString.ToString.Length))) Return Convert.ToDouble(intPart + fracPartNumerator / fracPartDenominator) End Function Private Function ConvertIntToString(ValueToConvert As Long) As String Dim result As String = String.Empty Dim targetBase As Long = GetEncodingCharsLength() Do result = GetEncodedChar(ValueToConvert Mod targetBase) & result ValueToConvert = ValueToConvert \ targetBase Loop While ValueToConvert > 0 Return result End Function Private Function ConvertSsortingngToInt(ValueToConvert As Ssortingng) As Long Dim result As Long Dim targetBase As Integer = GetEncodingCharsLength() Dim startBase As Integer = GetEncodingCharsStartBase() Dim value As Char For x As Integer = 0 To ValueToConvert.Length - 1 value = ValueToConvert(x) result += GetDecodedChar(value) * Convert.ToInt32(Math.Pow(GetEncodingCharsLength, ValueToConvert.Length - (x + 1))) Next Return result End Function Private Function GetEncodedChar(index As Integer) As Char If _CharacterArray IsNot Nothing AndAlso _CharacterArray.Count > 0 Then Return _CharacterArray(index) Else Return Convert.ToChar(index + NumberBaseLow) End If End Function Private Function GetDecodedChar(character As Char) As Integer If _CharacterArray IsNot Nothing AndAlso _CharacterArray.Count > 0 Then Return _CharacterArray.IndexOf(character) Else Return Convert.ToInt32(character) - NumberBaseLow End If End Function Private Function GetEncodingCharsLength() As Integer If _CharacterArray IsNot Nothing AndAlso _CharacterArray.Count > 0 Then Return _CharacterArray.Count Else Return NumberBaseHigh - NumberBaseLow + 1 End If End Function Private Function GetEncodingCharsStartBase() As Integer If _CharacterArray IsNot Nothing AndAlso _CharacterArray.Count > 0 Then Return GetHighLow.Key Else Return NumberBaseLow End If End Function End Class 

Et maintenant, pour que le code passe en boucle dans les colonnes Excel:

  Public Function GetColumnList(DataSheetID As Ssortingng) As List(Of Ssortingng) Dim workingColumn As New BaseNumber("A") workingColumn.SetCharacterArray("@ABCDEFGHIJKLMNOPQRSTUVWXYZ") Dim listOfPopulatedColumns As New List(Of Ssortingng) Dim countOfEmptyColumns As Integer Dim colHasData As Boolean Dim cellHasData As Boolean Do colHasData = True cellHasData = False For r As Integer = 1 To GetMaxRow(DataSheetID) cellHasData = cellHasData Or XLGetCellValue(DataSheetID, workingColumn.GetBaseXNumber & r) <> "" Next colHasData = colHasData And cellHasData 'keep trying until we get 4 empty columns in a row If colHasData Then listOfPopulatedColumns.Add(workingColumn.GetBaseXNumber) countOfEmptyColumns = 0 Else countOfEmptyColumns += 1 End If 'we are already starting with column A, so increment after we check column A Do workingColumn.SetNumber(workingColumn.GetBase10Number + 1) Loop Until Not workingColumn.GetBaseXNumber.Contains("@") Loop Until countOfEmptyColumns > 3 Return listOfPopulatedColumns End Function 

Vous remarquerez que la partie importante de la partie Excel est que 0 est identifié par un @ dans le numéro de nouvelle version. Donc, je filtre simplement tous les nombres qui ont un @ et j’obtiens la séquence correcte (A, B, C, …, Z, AA, AB, AC, …).

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConvertToAnyBase { class Program { static void Main(ssortingng[] args) { var baseNumber = int.Parse(Console.ReadLine()); var number = int.Parse(Console.ReadLine()); ssortingng conversion = ""; while(number!=0) { conversion += Convert.ToSsortingng(number % baseNumber); number = number / baseNumber; } var conversion2 = conversion.ToArray().Reverse(); Console.WriteLine(ssortingng.Join("", conversion2)); } } }