Convert.ToString
może służyć do konwersji liczby na jej równoważną reprezentację w postaci ciągu w określonej bazie.
Przykład:
string binary = Convert.ToString(5, 2); // convert 5 to its binary representation
Console.WriteLine(binary); // prints 101
Jednak, jak wskazano w komentarzach, Convert.ToString
obsługuje tylko następujący ograniczony - ale zazwyczaj wystarczający - zestaw podstaw: 2, 8, 10 lub 16.
Aktualizacja (aby spełnić wymóg konwersji na dowolną bazę):
Nie znam żadnej metody w BCL, która jest w stanie przekonwertować liczby na dowolną bazę, więc musiałbyś napisać własną małą funkcję użytkową. Prosty przykład wyglądałby tak (zauważ, że z pewnością można to zrobić szybciej, zastępując konkatenację ciągów):
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);
}
}
Aktualizacja 2 (poprawa wydajności)
Użycie buforu tablicy zamiast konkatenacji ciągów do skompilowania ciągu wynikowego zapewnia poprawę wydajności, szczególnie w przypadku dużej liczby (patrz metoda IntToStringFast
). W najlepszym przypadku (tj. Najdłuższym możliwym wejściu) ta metoda jest mniej więcej trzy razy szybsza. Jednak dla liczb 1-cyfrowych (czyli 1-cyfrowych w bazie docelowej), IntToString
będzie szybszy.
Niedawno pisałem o tym na blogu . Moja implementacja nie wykorzystuje podczas obliczeń żadnych operacji na łańcuchach, dzięki czemu jest bardzo szybka . Obsługiwana jest konwersja do dowolnego systemu liczbowego o podstawie od 2 do 36:
Zaimplementowałem również szybką funkcję odwrotną na wypadek, gdyby ktoś też jej potrzebował: Arbitrary to Decimal Numeral System .
źródło
result = "-" + result
? Czy to jakaś wyściółka? Jak mogę zmodyfikować kod, aby używać tylko AZ lub 0-9 jako znaku wypełniającego?"-"
Wresult = "-" + result
podpórek znakiem ujemnym liczb ujemnych. To nie jest znak wypełniający.SZYBKIE METODY „ OD ” I „ DO ”
Spóźniłem się na imprezę, ale zsumowałem poprzednie odpowiedzi i poprawiłem je. Myślę, że te dwie metody są szybsze niż jakiekolwiek inne opublikowane do tej pory. Byłem w stanie przekonwertować 1 000 000 liczb zi do podstawy 36 w czasie krótszym niż 400 ms na jednym rdzeniu.
Poniższy przykład dotyczy podstawy 62 . Zmień
BaseChars
tablicę, aby przekonwertować z i na dowolną inną podstawę.EDYCJA (12.07.2018)
Naprawiono rozwiązanie problemu narożnika znalezionego przez @AdrianBotor (patrz komentarze), konwertując 46655 na podstawę 36. Jest to spowodowane małym błędem zmiennoprzecinkowym,
Math.Log(46656, 36)
który wynosi dokładnie 3, ale .NET zwraca3 + 4.44e-16
, co powoduje dodatkowy znak w buforze wyjściowym .źródło
BaseToLong(LongToBase(46655)) == 46655
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
i przekonwertujmy wartość46655
. Wynik powinien być,ZZZ
ale w debugerze otrzymuję\0ZZZ
. Tylko ta wartość zyskuje dodatkową\0
. Na przykład wartość jest46654
prawidłowo konwertowana naZZY
.LongToBase
doreturn new string(buffer, (int) i, buffer.Length - (int)i);
Można też skorzystać z nieco zmodyfikowanej wersji akceptowanej i dostosować ciąg znaków bazowych do swoich potrzeb:
źródło
Bardzo późno na imprezę w tej sprawie, ale ostatnio napisałem następującą klasę pomocnika do projektu w pracy. Został zaprojektowany do konwersji krótkich ciągów na liczby iz powrotem (uproszczona, idealna funkcja skrótu ), jednak będzie również wykonywać konwersję liczb między dowolnymi zasadami.
Base10ToString
Realizacja metoda odpowiada na pytanie, który został pierwotnie opublikowany.shouldSupportRoundTripping
Potrzebna flaga przekazany do konstruktora klasy jest zapobieganie utracie wiodących cyfr z ciągiem liczb podczas konwersji do bazy-10 i z powrotem (ważne, biorąc pod uwagę moje wymagania!). W większości przypadków utrata wiodących zer z ciągu liczbowego prawdopodobnie nie będzie problemem.Tak czy inaczej, oto kod:
Można to również podzielić na podklasy, aby uzyskać niestandardowe konwertery liczb:
Kod zostałby użyty w ten sposób:
źródło
Czy te zajęcia z tego posta na forum mogą Ci pomóc?
Całkowicie nieprzetestowane ... daj mi znać, czy to działa! (Skopiuj i wklej go na wypadek, gdyby post na forum zniknął lub coś takiego ...)
źródło
Ja też szukałem szybkiego sposobu na zamianę liczby dziesiętnej na inną podstawę z zakresu [2..36], więc opracowałem następujący kod. Jest prosty do naśladowania i używa obiektu Stringbuilder jako proxy dla bufora znaków, który możemy indeksować znak po znaku. Kod wydaje się być bardzo szybki w porównaniu z alternatywami i dużo szybszy niż inicjalizacja pojedynczych znaków w tablicy znaków.
Na własny użytek możesz preferować: 1 / Zwróć pusty ciąg zamiast zgłaszać wyjątek. 2 / usuń sprawdzanie podstawy, aby metoda działała jeszcze szybciej 3 / Zainicjuj obiekt Stringbuilder z 32 '0 i usuń wynik linii.Remove (0, i) ;. Spowoduje to zwrócenie ciągu z zerami wiodącymi i dalsze zwiększenie szybkości. 4 / Uczyń obiekt Stringbuilder statycznym polem w klasie, więc bez względu na to, ile razy metoda DecimalToBase jest wywoływana, obiekt Stringbuilder jest inicjowany tylko raz. Jeśli to zrobisz, zmiana 3 powyżej przestanie działać.
Mam nadzieję, że komuś to się przyda :)
AtomicParadox
źródło
Używałem tego do przechowywania Guid jako krótszego ciągu (ale był ograniczony do użycia 106 znaków). Jeśli ktoś jest zainteresowany, to mój kod do dekodowania ciągu z powrotem do wartości liczbowej (w tym przypadku użyłem 2 ulongów dla wartości Guid, zamiast kodowania Int128 (ponieważ jestem w 3.5, a nie 4.0). Dla jasności KOD to string const z 106 unikalnymi znakami ConvertLongsToBytes jest dość nieciekawy.
źródło
Miałem podobną potrzebę, z wyjątkiem tego, że potrzebowałem też matematyki na „liczbach”. Skorzystałem z niektórych sugestii tutaj i stworzyłem klasę, która będzie robić te wszystkie fajne rzeczy. Pozwala na użycie dowolnego znaku Unicode do reprezentowania liczby i działa również z liczbami dziesiętnymi.
Ta klasa jest dość łatwa w użyciu. Po prostu utwórz liczbę jako typ
New BaseNumber
, ustaw kilka właściwości i wyłącz. Procedury zajmują się automatycznym przełączaniem między podstawą 10 a podstawą x, a ustawiona wartość jest zachowywana w bazie, w której ją ustawiłeś, więc nie ma utraty dokładności (to znaczy do konwersji, ale nawet wtedy utrata precyzji powinna być bardzo minimalna, ponieważ rutynowe zastosowaniaDouble
iLong
tam, gdzie to możliwe).Nie mogę kontrolować szybkości tej procedury. Prawdopodobnie jest dość powolny, więc nie jestem pewien, czy będzie odpowiadał potrzebom osoby, która zadał pytanie, ale na pewno jest elastyczny, więc mam nadzieję, że ktoś inny może go użyć.
Dla każdego, kto może potrzebować tego kodu do obliczenia następnej kolumny w programie Excel, dołączę kod pętli, którego użyłem, który wykorzystuje tę klasę.
A teraz, aby kod przechodził przez kolumny Excela:
Zauważysz, że ważną częścią części Excela jest to, że 0 jest identyfikowane przez @ w ponownie utworzonym numerze. Więc po prostu odfiltrowuję wszystkie liczby, które mają w sobie znak @ i otrzymuję odpowiednią sekwencję (A, B, C, ..., Z, AA, AB, AC, ...).
źródło
źródło
Jeśli ktoś szuka opcji VB, wynikało to z odpowiedzi Pawła:
źródło
Jest to dość prosty sposób, ale może nie być najszybszy. Jest dość potężny, ponieważ można go komponować.
Połącz to z tą prostą metodą rozszerzenia, a uzyskanie dowolnej bazy jest teraz możliwe:
Można go używać w następujący sposób:
Wynik to:
źródło