.NET에서 10 진수를 임의의 염기로 변환하는 가장 빠른 방법은 무엇입니까?
나는 숫자를 취하여 어떤 염기로도 변환하는 이전 (ish) C # 메소드를 가지고 있습니다.
string ConvertToBase(int number, char[] baseChars);
그다지 빠르고 깔끔한 것은 아닙니다. .NET에서 이것을 달성하는 잘 알려진 방법이 있습니까?
사용할 임의의 문자열로 모든 기본 을 사용할 수있는 것을 찾고 있습니다.
이것은 16, 10, 8 및 2 염기 만 허용합니다.
Convert.ToString(1, x);
나는 이것을 사용하여 숫자, 모두 소문자 및 모두 대문자를 활용하여 엄청나게 높은 기수를 얻고 싶습니다. 에서와 마찬가지로 이 스레드 ,하지만 C #을하지 자바 스크립트.
누구든지 C #에서 이것을 수행하는 훌륭하고 효율적인 방법을 알고 있습니까?
Convert.ToString
숫자를 지정된 밑수의 해당 문자열 표현으로 변환하는 데 사용할 수 있습니다.
예:
string binary = Convert.ToString(5, 2); // convert 5 to its binary representation
Console.WriteLine(binary); // prints 101
그러나 의견에서 지적한대로 Convert.ToString
에서는 제한적이지만 일반적으로 충분한 기준 세트 인 2, 8, 10 또는 16 만 지원합니다.
업데이트 (기본으로 변환하기위한 요구 사항 충족) :
나는 BCL에서 숫자를 어떤 염기로도 변환 할 수있는 방법을 알지 못하므로 자신 만의 작은 유틸리티 함수를 작성해야합니다. 간단한 샘플은 다음과 같습니다 (문자열 연결을 바꾸면 더 빨리 만들 수 있습니다).
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, A-Z)
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;
}
/// <summary>
/// An optimized method using an array as buffer instead of
/// string concatenation. This is faster for return values having
/// a length > 1.
/// </summary>
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);
}
}
업데이트 2 (성능 개선)
문자열 연결 대신 배열 버퍼를 사용하여 결과 문자열을 작성하면 특히 많은 수에서 성능이 향상됩니다 (method 참조 IntToStringFast
). 가장 좋은 경우 (즉, 가능한 가장 긴 입력)이 방법은 대략 3 배 더 빠릅니다. 그러나 1 자리 숫자 (즉, 대상 기준의 1 자리 숫자)의 IntToString
경우 더 빠릅니다.
나는 최근에 이것에 대해 블로그에 올렸다 . 내 구현은 계산 중에 문자열 연산을 사용하지 않으므로 매우 빠릅니다 . 2에서 36까지의 기본 숫자 체계로의 변환이 지원됩니다.
/// <summary>
/// Converts the given decimal number to the numeral system with the
/// specified radix (in the range [2, 36]).
/// </summary>
/// <param name="decimalNumber">The number to convert.</param>
/// <param name="radix">The radix of the destination numeral system (in the range [2, 36]).</param>
/// <returns></returns>
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;
}
또한 누구나 필요로하는 경우를 대비하여 빠른 역함수를 구현했습니다. Arbitrary to Decimal Numeral System .
FAST " FROM AND" " TO "방법
나는 파티에 늦었지만 이전 답변을 합성하고 개선했습니다. 이 두 가지 방법이 지금까지 게시 된 다른 방법보다 빠르다고 생각합니다. 단일 코어 머신에서 400ms 이내에 1,000,000 개의 숫자를 기본 36으로 변환 할 수있었습니다.
아래의 예는 기본 62 입니다. BaseChars
다른 염기로 변환 하려면 배열을 변경하십시오 .
private static readonly char[] BaseChars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();
private static readonly Dictionary<char, int> 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;
}
수정 (2018-07-12)
46655를 기준 36으로 변환하는 @AdrianBotor (주석 참조)에서 발견 된 코너 케이스를 해결하도록 수정되었습니다. 이는 Math.Log(46656, 36)
정확히 3 인 계산의 작은 부동 소수점 오류 3 + 4.44e-16
로 인해 발생 하지만 .NET 이을 반환 하여 출력 버퍼에 추가 문자가 발생합니다. .
허용되는 버전의 약간 수정 된 버전을 사용하고 필요에 따라 기본 문자열을 조정할 수도 있습니다.
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;
}
이것에 대한 파티에 매우 늦었지만 최근에 직장에서 프로젝트를 위해 다음 도우미 클래스를 작성했습니다. 짧은 문자열을 숫자로 변환하고 다시 되돌 리도록 설계 되었지만 (단순한 완벽한 해시 함수) 임의의 염기간에 숫자 변환도 수행합니다. Base10ToString
메소드 구현은 원래 게시 된 질문에 대한 대답.
shouldSupportRoundTripping
클래스 생성자에 전달 된 플래그는 10 진수로 변환하는 동안 숫자 문자열에서 선행 자릿수가 손실되는 것을 방지하기 위해 필요합니다 (내 요구 사항을 고려할 때 중요합니다!). 대부분의 경우 숫자 문자열에서 선행 0이 손실되는 것은 문제가되지 않을 것입니다.
어쨌든 다음은 코드입니다.
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackOverflow
{
/// <summary>
/// Contains methods used to convert numbers between base-10 and another numbering system.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// The first digit in the sequence has special significance. If the number passed to the
/// <see cref="StringToBase10"/> 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 <see cref="System.Boolean"/>
/// flag passed to the constructor allows 'round-tripping' behaviour to be supported, which will prevent
/// leading digits from being lost during conversion.
/// </para>
/// <para>
/// Note that numeric overflow is probable when using longer strings and larger digit sets.
/// </para>
/// </remarks>
public class Base10Converter
{
const char NullDigit = '\0';
public Base10Converter(string digits, bool shouldSupportRoundTripping = false)
: this(digits.ToCharArray(), shouldSupportRoundTripping)
{
}
public Base10Converter(IEnumerable<char> 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<char, int> _digitToIndexMap;
readonly Dictionary<int, char> _indexToDigitMap;
readonly int _radix;
public long StringToBase10(string number)
{
Func<char, int, long> 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;
}
}
}
이것은 또한 사용자 지정 숫자 변환기를 파생하기 위해 하위 분류 될 수 있습니다.
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)
{
}
}
}
그리고 코드는 다음과 같이 사용됩니다.
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);
}
}
}
}
이 포럼 게시물 의이 수업 이 도움 이 될 수 있습니까?
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;
}
}
완전히 테스트되지 않았습니다 ... 작동하는지 알려주세요! (포럼 게시물이 사라지는 경우를 대비하여 복사-붙여 넣기 ...)
나도 십진수를 [2..36] 범위의 다른 밑으로 변환하는 빠른 방법을 찾고 있었기 때문에 다음 코드를 개발했습니다. 따라 가기 쉽고 Stringbuilder 객체를 문자별로 인덱싱 할 수있는 문자 버퍼의 프록시로 사용합니다. 코드는 대안에 비해 매우 빠르며 문자 배열에서 개별 문자를 초기화하는 것보다 훨씬 빠릅니다.
자신의 사용을 위해 다음을 선호 할 수 있습니다. 1 / 예외를 던지기보다는 빈 문자열을 반환합니다. 2 / 메서드가 더 빠르게 실행되도록 기수 검사를 제거합니다. 3 / 32 '0'으로 Stringbuilder 객체를 초기화하고 result.Remove (0, i); 줄을 제거합니다. 이렇게하면 문자열이 선행 0으로 반환되고 속도가 더욱 빨라집니다. 4 / Stringbuilder 객체를 클래스 내에서 정적 필드로 만들어 DecimalToBase 메서드가 몇 번 호출 되든 Stringbuilder 객체는 한 번만 초기화됩니다. 이 변경을 수행하면 위의 3이 더 이상 작동하지 않습니다.
누군가 이것이 유용하다고 생각하기를 바랍니다 :)
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());
}
나는 이것을 사용하여 Guid를 더 짧은 문자열로 저장했습니다 (그러나 106 자로 제한되었습니다). 여기에 관심이있는 사람은 문자열을 다시 숫자 값으로 디코딩하는 코드입니다 (이 경우에는 Int128을 코딩하는 대신 Guid 값에 2 ulong을 사용했습니다 (4.0이 아닌 3.5에 있음). 명확성을 위해 CODE는 106 개의 고유 문자를 가진 문자열 const.ConvertLongsToBytes는 꽤 흥미롭지 않습니다.
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);
}
}
나는 "숫자"에 대해서도 수학을해야한다는 것을 제외하고는 비슷한 필요가 있었다. 여기에서 몇 가지 제안을 받아이 모든 재미있는 일을 할 수있는 수업을 만들었습니다. 유니 코드 문자를 사용하여 숫자를 나타내는 데 사용할 수 있으며 소수에서도 작동합니다.
이 클래스는 사용하기 매우 쉽습니다. 유형으로 번호를 만들고 New BaseNumber
몇 가지 속성을 설정 한 다음 해제하면됩니다. 루틴은 기본 10과 기본 x 사이를 자동으로 전환하며 설정 한 값은 설정 한 기본에 보존되므로 정확도가 손실되지 않습니다 (즉, 변환 할 때까지는 정밀도 손실이 매우 미미해야합니다. 일상적인 사용 Double
및 Long
가능한 경우).
이 루틴의 속도를 명령 할 수 없습니다. 아마도 꽤 느리기 때문에 질문을 한 사람의 요구에 맞는지 확실하지 않지만 확실히 유연하므로 다른 사람이 이것을 사용할 수 있기를 바랍니다.
Excel에서 다음 열을 계산하는 데이 코드가 필요한 다른 사람을 위해이 클래스를 활용하는 루핑 코드를 포함하겠습니다.
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
이제 코드가 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
Excel 부분의 중요한 부분은 다시 기반 번호에서 0이 @로 식별된다는 것입니다. 그래서 저는 @가있는 모든 숫자를 걸러 내고 적절한 시퀀스 (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));
}
}
}
'development' 카테고리의 다른 글
Backbone.js :`extend`가 정의되지 않았습니까? (0) | 2020.08.14 |
---|---|
함수를 사용하여 가장 가까운 분 및 가장 가까운 시간으로 반올림 된 T-SQL datetime (0) | 2020.08.14 |
메서드에서 두 개 이상의 값 반환 (0) | 2020.08.14 |
Linux의 PostgreSQL 데이터베이스 기본 위치 (0) | 2020.08.14 |
MSBuild.exe를 사용하여 릴리스 모드에서 C # 솔루션 빌드 (0) | 2020.08.14 |