Maneira mais rápida de converter um número base 10 em qualquer base no .NET?

Eu tenho e velho (ish) método C # eu escrevi que leva um número e converte-lo para qualquer base:

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

Não é tudo tão rápido e arrumado. Existe uma maneira boa e conhecida de conseguir isso no .net?

Eu estou procurando por algo que me permite usar qualquer base com uma seqüência arbitrária de caracteres para usar.

Isso só permite as bases 16, 10, 8 e 2:

 Convert.ToString(1, x); 

Eu quero usar isso para conseguir uma base massivamente alta aproveitando os números, todas as letras minúsculas e todas as letras maiúsculas. Como neste segmento , mas para C # não JavaScript.

Alguém sabe de uma maneira boa e eficiente de fazer isso em c #?

Convert.ToString pode ser usado para converter um número em sua representação de string equivalente em uma base especificada.

Exemplo:

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

No entanto, como apontado pelos comentários, o Convert.ToString suporta apenas o seguinte conjunto de bases limitado – mas normalmente suficiente -: 2, 8, 10 ou 16.

Atualização (para atender ao requisito de conversão para qualquer base):

Eu não estou ciente de qualquer método na BCL que é capaz de converter números para qualquer base, assim você teria que escrever sua própria function de utilidade pequena. Um exemplo simples ficaria assim (note que isso certamente pode ser feito mais rapidamente substituindo a concatenação de strings):

 class Program { static void Main(string[] args) { // convert to binary string binary = IntToString(42, new char[] { '0', '1' }); // convert to hexadecimal string hex = IntToString(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) string hexavigesimal = IntToString(42, Enumerable.Range('A', 26).Select(x => (char)x).ToArray()); // convert to sexagesimal string xx = IntToString(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 string IntToString(int value, char[] baseChars) { string result = string.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 /// string concatenation. This is faster for return values having /// a length > 1. ///  public static string IntToStringFast(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 string(result); } } 

Atualização 2 (Melhoria de Desempenho)

Usar um buffer de matriz em vez de concatenação de sequência para criar a sequência de resultados fornece uma melhoria de desempenho especialmente em grande número (consulte o método IntToStringFast ). No melhor dos casos (ou seja, a maior input possível), este método é aproximadamente três vezes mais rápido. No entanto, para números de 1 dígito (ou seja, 1 dígito na base de destino), o IntToString será mais rápido.

Eu recentemente bloguei sobre isso . Minha implementação não usa nenhuma operação de string durante os cálculos, o que a torna muito rápida . A conversão para qualquer sistema numeral com base de 2 a 36 é suportada:

 ///  /// 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 string DecimalToArbitrarySystem(long decimalNumber, int radix) { const int BitsInLong = 64; const string 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; } 

Eu também implementei uma function inversa rápida no caso de alguém precisar também: Sistema Numeral Arbitrário para Decimal .

Também é possível usar uma versão ligeiramente modificada do aceito e ajustar a sequência de caracteres de base às suas necessidades:

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

Muito tarde para a festa, mas escrevi a seguinte aula de ajuda para um projeto no trabalho. Ele foi projetado para converter strings curtas em números e vice-versa (uma function hash simplista), no entanto, ele também executa conversão de números entre bases arbitrárias. A implementação do método Base10ToString responde à pergunta que foi originalmente postada.

O sinalizador shouldSupportRoundTripping passado para o construtor de class é necessário para evitar a perda de dígitos shouldSupportRoundTripping da cadeia numérica durante a conversão para a base 10 e vice-versa (crucial, considerando meus requisitos!). Na maioria das vezes, a perda dos 0s iniciais da sequência numérica provavelmente não será um problema.

De qualquer forma, aqui está o código:

 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-tripping' behaviour to be supported, which will prevent /// leading digits from being lost during conversion. ///  ///  /// Note that numeric overflow is probable when using longer strings and larger digit sets. ///  ///  public class Base10Converter { const char NullDigit = '\0'; public Base10Converter(string 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 StringToBase10(string number) { Func selector = (c, i) => { int power = number.Length - i - 1; int digitIndex; if (!_digitToIndexMap.TryGetValue(c, out digitIndex)) { throw new ArgumentException( message: String.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 string Base10ToString(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; } } } 

Isso também pode ser subclassificado para derivar conversores de números personalizados:

 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) { } } } 

E o código seria usado assim:

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

MÉTODOS RÁPIDOS ” DE ” E ” PARA

Estou atrasado para a festa, mas acrescentei respostas anteriores e melhorei com elas. Eu acho que esses dois methods são mais rápidos do que qualquer outro publicado até agora. Consegui converter 1.000.000 de números e de base 36 em menos de 400ms em uma máquina de núcleo único.

O exemplo abaixo é para a base 62 . Altere a matriz BaseChars para converter de e para qualquer outra 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 string 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 string(buffer, i, buffer.Length - i); } public static long BaseToLong(string 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)

Corrigido para endereçar o caso de canto encontrado por @AdrianBotor (ver comentários) convertendo 46655 para a base 36. Isto é causado por um pequeno erro de ponto flutuante calculando Math.Log(46656, 36) que é exatamente 3, mas o .NET retorna 3 + 4.44e-16 , que causa um caractere extra no buffer de saída.

Esta turma deste fórum pode ajudar você?

 public class BaseConverter { public static string ToBase(string number, int start_base, int target_base) { int base10 = this.ToBase10(number, start_base); string rtn = this.FromBase10(base10, target_base); return rtn; } public static int ToBase10(string 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.ToString()); else x = Convert.ToInt32(c) - 55; rtn += x * (Convert.ToInt32(Math.Pow(n, m))); m--; } return rtn; } public static string FromBase10(int number, int target_base) { if (target_base < 2 || target_base > 36) return ""; if (target_base == 10) return number.ToString(); int n = target_base; int q = number; int r; string 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; } } 

Totalmente não testado ... deixe-me saber se funciona! (Copie-colou no caso de o post do fórum desaparecer ou algo assim ...)

Eu também estava procurando uma maneira rápida de converter um número decimal em outra base no intervalo de [2..36], então desenvolvi o seguinte código. É simples de seguir e usa um object Stringbuilder como um proxy para um buffer de caracteres que podemos indexar caractere por caractere. O código parece ser muito rápido comparado a alternativas e muito mais rápido do que inicializar caracteres individuais em uma matriz de caracteres.

Para seu próprio uso, você pode preferir: 1 / Retornar uma string em branco em vez de lançar uma exceção. 2 / remova a verificação radix para tornar o método mais rápido ainda 3 / Inicialize o object Stringbuilder com 32 ‘0s e remova o resultado da linha. Retire (0, i) ;. Isso fará com que a string seja retornada com zeros à esquerda e aumente ainda mais a velocidade. 4 / Torne o object Stringbuilder um campo estático dentro da class, portanto, não importa quantas vezes o método DecimalToBase é chamado, o object Stringbuilder é inicializado apenas uma vez. Se você fizer isso, a alteração 3 acima não funcionará mais.

Espero que alguém ache isso útil 🙂

AtomicParadox

  static string 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 StringBuilder result = new StringBuilder(" "); // 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.ToString()); } 

Eu estava usando isso para armazenar um Guid como uma seqüência mais curta (mas foi limitado a usar 106 caracteres). Se alguém está interessado aqui é o meu código para decodificar a seqüência de volta ao valor numérico (neste caso eu usei 2 ulongs para o valor Guid, em vez de codificar um Int128 (já que estou em 3.5 não 4.0). string const com 106 caracteres únicos. ConvertLongsToBytes é bem desinteressante.

 private static Guid B106ToGuid(string 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); } } 

Eu tinha uma necessidade semelhante, exceto que eu precisava fazer contas nos “números” também. Eu peguei algumas das sugestões aqui e criei uma class que fará todas essas coisas divertidas. Ele permite que qualquer caractere unicode seja usado para representar um número e também funciona com decimais.

Esta class é muito fácil de usar. Basta criar um número como um tipo de New BaseNumber , definir algumas propriedades e seu off. As rotinas tomam o cuidado de alternar entre a base 10 e a base x automaticamente e o valor definido é preservado na base em que você o configura, portanto nenhuma precisão é perdida (até a conversão, mas mesmo assim a perda de precisão deve ser mínima rotina usa Double e Long sempre que possível).

Eu não posso comandar a velocidade dessa rotina. É provavelmente muito lento, por isso não tenho a certeza se irá atender às necessidades de quem fez a pergunta, mas é certo que é flexível, por isso espero que alguém possa usar isto.

Para qualquer outra pessoa que precise desse código para calcular a próxima coluna no Excel, includeei o código de loop que usei para aproveitar essa class.

 Public Class BaseNumber Private _CharacterArray As List(Of Char) Private _BaseXNumber As String 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 String) _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 String) _BaseXNumber = Value _Base10Number = Nothing End Sub Public Sub SetNumber(Value As Double) _Base10Number = Value _BaseXNumber = Nothing End Sub Public Function GetBaseXNumber() As String If _BaseXNumber IsNot Nothing Then Return _BaseXNumber Else Return ToBaseString() 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 string 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 string 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 ToBaseString() As String Dim Base10Number As Double = _Base10Number Dim intPart As Long = Math.Truncate(Base10Number) Dim fracPart As Long = (Base10Number - intPart).ToString.Replace(DecimalSeparator, "") Dim intPartString As String = ConvertIntToString(intPart) Dim fracPartString As String = 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 ConvertStringToInt(ValueToConvert As String) 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 

E agora, para o código percorrer as colunas do Excel:

  Public Function GetColumnList(DataSheetID As String) As List(Of String) Dim workingColumn As New BaseNumber("A") workingColumn.SetCharacterArray("@ABCDEFGHIJKLMNOPQRSTUVWXYZ") Dim listOfPopulatedColumns As New List(Of String) 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 

Você notará que a parte importante da parte do Excel é que 0 é identificado por um @ no número baseado em novo. Então eu apenas filtro todos os números que possuem um @ e eu obtenho a seqüência correta (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(string[] args) { var baseNumber = int.Parse(Console.ReadLine()); var number = int.Parse(Console.ReadLine()); string conversion = ""; while(number!=0) { conversion += Convert.ToString(number % baseNumber); number = number / baseNumber; } var conversion2 = conversion.ToArray().Reverse(); Console.WriteLine(string.Join("", conversion2)); } } }