La forma más rápida de convertir un número base 10 a cualquier base en .NET?

Tengo un método antiguo (ish) C # que escribí que toma un número y lo convierte a cualquier base:

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

No es tan súper rápido y ordenado. ¿Hay alguna manera buena y conocida de lograr esto en .NET?

Estoy buscando algo que me permita usar cualquier base con una cadena arbitraria de caracteres para usar.

Esto solo permite las bases 16, 10, 8 y 2:

 Convert.ToString(1, x); 

Quiero utilizar esto para lograr una base enormemente alta aprovechando los números, todas las minúsculas y todas las letras mayúsculas. Al igual que en este hilo , pero para C # no JavaScript.

¿Alguien sabe de una manera buena y eficiente de hacer esto en C #?

Convert.ToString se puede usar para convertir un número a su representación de cadena equivalente en una base específica.

Ejemplo:

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

Sin embargo, como se señala en los comentarios, Convert.ToString solo admite las siguientes bases limitadas, pero generalmente suficientes: 2, 8, 10 o 16.

Actualización (para cumplir con el requisito de convertir a cualquier base):

No conozco ningún método en el BCL que sea capaz de convertir números a cualquier base, así que tendría que escribir su propia pequeña función de utilidad. Una muestra simple se vería así (tenga en cuenta que esto seguramente se puede hacer más rápido reemplazando la concatenación de cadenas):

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

Actualización 2 (Mejora del rendimiento)

El uso de un búfer de matriz en lugar de concatenación de cadenas para generar la cadena de resultados proporciona una mejora en el rendimiento, especialmente en números grandes (consulte el método IntToStringFast ). En el mejor de los casos (es decir, la entrada más larga posible), este método es aproximadamente tres veces más rápido. Sin embargo, para números de 1 dígito (es decir, 1 dígito en la base del objective), IntToString será más rápido.

Hace poco publiqué sobre esto . Mi implementación no usa ninguna operación de cadena durante los cálculos, lo que la hace muy rápida . Se admite la conversión a cualquier sistema numérico con una base de 2 a 36:

 ///  /// 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; } 

También he implementado una función inversa rápida en caso de que alguien lo necesite también: Arbitrario a sistema numérico decimal .

También se puede usar una versión ligeramente modificada del aceptado y ajustar la cadena de caracteres base a sus necesidades:

 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; } 

Muy tarde para la fiesta en este caso, pero escribí la siguiente clase de ayudante recientemente para un proyecto en el trabajo. Fue diseñado para convertir cadenas cortas en números y viceversa (una función hash perfecta simplista), sin embargo, también realizará conversión de números entre bases arbitrarias. La Base10ToString método Base10ToString responde a la pregunta que se publicó originalmente.

El indicador shouldSupportRoundTripping pasado al constructor de la clase es necesario para evitar la pérdida de dígitos shouldSupportRoundTripping de la cadena numérica durante la conversión a base-10 y viceversa (¡crucial, dado mis requisitos!). La mayoría de las veces, la pérdida de los 0 iniciales de la cadena numérica probablemente no sea un problema.

De todos modos, aquí está el 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; } } } 

Esto también se puede subclasificar para derivar convertidores 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) { } } } 

Y el código se usaría así:

 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 ” DESDE ” Y ” A

Llego tarde a la fiesta, pero he compuesto respuestas anteriores y las he mejorado. Creo que estos dos métodos son más rápidos que los publicados hasta el momento. Pude convertir 1,000,000 números desde y hasta la base 36 en menos de 400ms en una máquina de un solo núcleo.

El siguiente ejemplo es para la base 62 . Cambie la matriz BaseChars para convertir desde y hacia cualquier otra 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; } 

EDITAR (2018-07-12)

Solucionado para abordar el caso de esquina encontrado por @AdrianBotor (ver comentarios) convirtiendo 46655 en base 36. Esto es causado por un pequeño error de punto flotante calculando Math.Log(46656, 36) que es exactamente 3, pero .NET devuelve 3 + 4.44e-16 , que causa un carácter adicional en el búfer de salida.

¿Podría esta clase de esta publicación en el foro ayudarte?

 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 no probado ... ¡avísame si funciona! (Copiar y pegar en caso de que la publicación del foro desaparezca o algo así ...)

Yo también estaba buscando una manera rápida de convertir un número decimal a otra base en el rango de [2..36], así que desarrollé el siguiente código. Es simple de seguir y utiliza un objeto Stringbuilder como proxy para un búfer de caracteres que podemos indexar carácter por carácter. El código parece ser muy rápido en comparación con las alternativas y mucho más rápido que la inicialización de caracteres individuales en una matriz de caracteres.

Para su propio uso, quizás prefiera: 1 / Devolver una cadena en blanco en lugar de lanzar una excepción. 2 / elimine la comprobación de radix para hacer que el método se ejecute aún más rápido 3 / Inicialice el objeto Stringbuilder con 32 ‘0’s y elimine el resultado de la línea. Elimine (0, i) ;. Esto hará que la cadena se devuelva con ceros a la izquierda y aumente aún más la velocidad. 4 / Haga del objeto Stringbuilder un campo estático dentro de la clase, así que no importa cuántas veces se llame al método DecimalToBase, el objeto Stringbuilder solo se inicializa una vez. Si lo hace, el cambio 3 anterior ya no funcionará.

Espero que alguien encuentre esto ú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()); } 

Estaba usando esto para almacenar un Guid como una cadena más corta (pero estaba limitado a usar 106 caracteres). Si alguien está interesado aquí, mi código para decodificar la cadena vuelve al valor numérico (en este caso, utilicé 2 ulongs para el valor Guid, en lugar de codificar un Int128 (dado que estoy en 3.5 no 4.0). Para mayor claridad, CODE es un const de cadena con 106 caracteres únicos. ConvertLongsToBytes es bastante aburrido.

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

Tenía una necesidad similar, excepto que también necesitaba hacer cálculos matemáticos sobre los “números”. Tomé algunas de las sugerencias aquí y creé una clase que hará todas estas cosas divertidas. Permite que cualquier carácter Unicode se use para representar un número y también funciona con decimales.

Esta clase es bastante fácil de usar. Simplemente cree un número como un tipo de New BaseNumber , configure algunas propiedades y su off. Las rutinas se ocupan de cambiar entre la base 10 y la base x automáticamente y el valor que estableces se conserva en la base en la que lo configuraste, por lo que no se pierde precisión (hasta la conversión, pero incluso entonces la pérdida de precisión debería ser mínima ya que la rutina usa Double y Long siempre que sea posible).

No puedo mandar sobre la velocidad de esta rutina. Es probable que sea bastante lento, así que no estoy seguro de si se adaptará a las necesidades de quien hizo la pregunta, pero es cierto que es flexible, así que con suerte alguien más puede usar esto.

Para cualquier otra persona que pueda necesitar este código para calcular la próxima columna en Excel, incluiré el código de bucle que utilicé y que aprovecha esta clase.

 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 

Y ahora para que el código pase por las columnas de 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 

Notará que la parte importante de la parte de Excel es que 0 se identifica con un @ en el número de referencia. Así que filtré todos los números que tienen una @ en ellos y obtengo la secuencia correcta (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)); } } }