Click here to Skip to main content
Email Password   helpLost your password?

Introduction

C# conversion functions are very powerful. The Convert class has many methods that perform typical conversion of a string to integer, and other data types. One of the functions ToInt64() not only converts a given value to a 64-bit integer but also returns the number to the specified base.

Convert.ToInt64(value,16);

The above function converts a decimal number to hexadecimal number. This is most useful in situations where you write programs for arithmetic calculations. I thought of writing my own function that does this kind of conversion. I created two functions, DecimalToBase which converts any decimal number to a binary, octal or hexadecimal number and BaseToDecimal which converts any binary, octal or hexadecimal number to the corresponding decimal number.

The most interesting part is that both the functions are generic in nature. In the DecimalToBase function, I had to write the algorithm that can perform the conversion of a decimal to binary, octal or hexadecimal. I had to write the code for all of these conversions within a single function, still keeping my code reduced to handle all sorts of values. C#�s type-safe nature prevents us from doing some easier character-int conversions and we just can�t surpass them, as it would produce adverse results. Same is the case with the BaseToDecimal function.

A sample application to test the conversion functions

Sample Output #1:

Sample Output #2:

Sample Output #3:

Sample Output #4:

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralMy New Version - Using bitwise-AND operator [modified]
dciobanu2007@gmail.com
11:53 23 Apr '09  
static readonly char[] m_sDigit = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static string DecimalToBase(int decimalNumber, int baseNumber)
{
if (baseNumber != 2)
if(baseNumber != 8)
if(baseNumber != 16)
return string.Empty;

uint val = (uint)decimalNumber;

StringBuilder binaryHolder = new StringBuilder();

int mask = 0, bits = 0;
if (baseNumber == 2)
{
mask = 1;
bits = 31;
}
else if (baseNumber == 8)
{
mask = 3;
bits = 30;
}
else if (baseNumber == 16)
{
mask = 4;
bits = 28;
}

baseNumber -=1;
for (; bits >= 0; bits -= mask)
{
binaryHolder.Append(m_sDigit[(val >> bits) & (baseNumber)]);
}
return binaryHolder.ToString();
}


DC
dciobanu2007@gmail.com

modified on Saturday, April 25, 2009 12:17 PM

GeneralBig numbers problem
kavy777
23:42 11 Feb '09  
Thank you for your worthy program.
I am new in C# and I need to do this conversion in one of my programs, but I am working with big numbers. i.e. 10^120 or bigger. Could you help me and say that how can I manage it while using this algorithm?
Thank you.
GeneralMy Versions
kender_2
9:01 16 Jul '07  
For any base from 2 to 62, handles negatives and zeroes:
public static int BaseToDecimal(string input, int nBase)
{
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (nBase < 2 || nBase > characters.Length)
{
throw new ArgumentOutOfRangeException("nBase", nBase, "Range: 2.." + characters.Length);
}
int result = 0;
bool negative = false;
if (input.StartsWith("-"))
{
negative = true;
input = input.Substring(1);
}
for (int i = 0; i < input.Length; i++)
{
int value = characters.IndexOf(input[i]);
if (value >= nBase || value < 0)
{
throw new ArgumentOutOfRangeException("input[" + i + "]", input[i], "This character is not valid for base " + nBase);
}
result += value * (int)Math.Pow(nBase, input.Length - i - 1);
}
if (negative)
{
result *= -1;
}
return result;
}
public static string DecimalToBase(int input, int nBase)
{
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (nBase < 2 || nBase > characters.Length)
{
throw new ArgumentOutOfRangeException("nBase", nBase, "Range: 2.." + characters.Length);
}
if (input == 0)
{
return characters[0].ToString();
}
bool negative = false;
if (input < 0)
{
negative = true;
input *= -1;
}
StringBuilder sb = new StringBuilder();
while (input != 0)
{
sb.Insert(0, (characters[input % nBase]));
input /= nBase;
}
if (negative)
{
sb.Insert(0, "-");
}
return sb.ToString();
}
Converts 1 to million to hex and back again in .841 seconds.
No zero padding though, that's what we have String.Format for.
GeneralRe: My Versions
Shabbazz
2:05 7 Aug '07  
Hi,

exactly what I was looking for. Many thanks.
Volker
GeneralRe: My Versions
blackjack2150
21:49 17 Oct '07  
Very useful. Thanks!
GeneralRe: My Versions
ajones78
12:58 9 Nov '07  
This is good but has one fatal flaw.

Try calling it like this:

DecimalToBase(int.MinValue, 16);
This causes an error due to the attempt to support negative signs on the final string. The problem is that the MinValue for Int has no corresponding positive value so doing this:

input *= -1;
doesn't actually change the sign. To get around this one would have to use uint and determine if the number should be negative or not. Like so:

public static string DecimalToBase(int input, uint nBase) {
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (nBase < 2 || nBase > characters.Length) {
throw new ArgumentOutOfRangeException("nBase", nBase, "Range: 2.." + characters.Length);
}
if (input == 0) {
return characters[0].ToString();
}

uint uInput = unchecked((uint)input);
bool negative = uInput > (uint)int.MaxValue;

if (negative) {
//calculate the distance from the highest possible value minus 2
uint diff = uInput - (uint)int.MaxValue - 2;
Console.WriteLine(diff);
uInput = (uint)int.MaxValue - diff;
}

StringBuilder sb = new StringBuilder();
while (uInput != 0) {
sb.Insert(0, (characters[(int)(uInput % nBase)]));
uInput /= nBase;
}

if (negative) {
sb.Insert(0, "-");
}
return sb.ToString();
}

This will work for all the various bases supported. Also for larger numbers use long and ulong in place of int and uint.
GeneralRe: My Versions
ajones78
13:24 9 Nov '07  
Follow-Up.

Working with this more, I've added a means by which to get either the signed or unsigned equivalent of the number sent in.

Using HEX for example the integer value -2147483647 would come out as -7FFFFFFF if you wanted the negative sign appended (like the above method does). But what if you didn't want the signed version and wanted how it would actually be represented in the system or (if not using HEX how it'd be if not signed). It should be 80000001 (hex).

Here's the modified code to do both:

public static string DecimalToBase(int input, uint nBase, bool signed) {
string characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if (nBase < 2 || nBase > characters.Length) {
throw new ArgumentOutOfRangeException("nBase", nBase, "Range: 2.." + characters.Length);
}
if (input == 0) {
return characters[0].ToString();
}

uint uInput = unchecked((uint)input);
bool negative = false;

if (signed) {
negative = uInput > (uint)int.MaxValue;

if (negative) {
//calculate the distance from the highest possible value minus 2
uint diff = uInput - (uint)int.MaxValue - 2;
uInput = (uint)int.MaxValue - diff;
}
}

StringBuilder sb = new StringBuilder();
while (uInput != 0) {
sb.Insert(0, (characters[(int)(uInput % nBase)]));
uInput /= nBase;
}

if (negative) {
sb.Insert(0, "-");
}
return sb.ToString();
}

GeneralRe: My Versions
Elad Moshe
23:11 16 Aug '09  
Thanks, works great Smile
GeneralThanks :-D
jackmandile
9:52 22 Nov '06  
Hi,

This was very helpful to me.
Thank you very much.

jack
GeneralWonderful
Fahad Azeem
22:28 24 Nov '05  
This was good. Helped me a lot.
Thanks...!

Nothing is impossible.....even impossible has the word possible
GeneralImprovement
Nigel Savidge
5:52 15 Sep '05  
Thanks for the article - I just made use of the DecimalToBase method but found it doesn't give "0" - it gives "" instead. Also it doesn't do negative numbers.

I have made a few changes including:

fixing the 0 problem,

Support for negative numbers,

adding a zeroPadding parameter - set to 1 to get "0", 0 to get "" as before and 4 to get "0001" etc.

Improvement to the speed - to do all numbers 0 to 1 million in hex was taking 33 seconds, with this new version it takes 0.8 seconds.

private string DecimalToBase(int iDec, int numberBase, int zeroPadding)
{
if (numberBase > 16 || numberBase < 2) throw new System.ArgumentOutOfRangeException ("numberBase", numberBase, "numberBase - Range: 2..16") ;
if (zeroPadding < 0) throw new System.ArgumentOutOfRangeException ("zeroPadding", zeroPadding, "zeroPadding should be positive") ;

System.Text.StringBuilder str = new System.Text.StringBuilder() ;
bool negative ;

if (iDec < 0)
{
negative = true ;
iDec *=-1 ;
}
else {
negative = false ;
}

int MaxBit = 32;
int max = MaxBit ;
int[] result = new int[MaxBit];

for(; iDec > 0; iDec/=numberBase)
{
int rem = iDec % numberBase;
result[--max] = rem;
}

if (iDec > 0) throw new System.ArgumentOutOfRangeException ("iDec", iDec, "iDec - Too large") ;

for (int i=max;i {
str.Append(cHexa[result[i]]);
}
int zeroPaddingRequired = zeroPadding - (MaxBit - max) ;
if (zeroPaddingRequired > 0) str.Insert (0, new string('0',zeroPaddingRequired)) ;
if (negative) str.Insert (0, '-') ;
return str.ToString();
}

[NonSerialized()]private char[] cHexa = new char[]{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
Hope someone finds it usefull Smile


Team Leader - Team Code Project[^] Cool
GeneralRe: Improvement [modified]
Lemuel.Adane
22:56 12 May '08  
Hey Nigel

I think you have a typo error at "if (int i=max;i {str.Append(cHexa[result[i]]); }"...

_
modified on Tuesday, June 3, 2008 5:44 AM

GeneralRe: Improvement
Nigel Savidge
6:03 14 May '08  
Oops,

Appologies for loosing a bit Sigh

But it looks like you have fixed it now anyway Wink


Team Leader - Team Code Project[^] Cool

GeneralRe: Improvement [modified]
Lemuel.Adane
5:05 14 May '08  
Anyway, I debugged it and below is the result. I just had to renamed all the variables to follow my coding standard. Thanks to you and to Balamurali, because I used this routine in my project.


[NonSerialized()]

private char[] hexCharacters = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };




private string DecimalToBase(int decimal_number, int number_base, int zero_padding)
{
if (number_base > 16 || number_base < 2)
{
throw new System.ArgumentOutOfRangeException (
"number_base", number_base, "number_base - Range: 2..16");
}

if (zero_padding < 0)
{
throw new System.ArgumentOutOfRangeException (
"zero_padding", zero_padding, "zero_padding should be positive");
}

System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();

bool isNegative = false;

if (decimal_number < 0)
{
isNegative = true ;

decimal_number *=-1 ;
}
else
{
isNegative = false ;
}

const int MAX_BIT = 32;

int max = MAX_BIT;

int[] remainders = new int[MAX_BIT];

for(; decimal_number > 0; decimal_number /= number_base)
{
remainders[--max] = decimal_number % number_base;
}

if (decimal_number > 0)
{
throw new System.ArgumentOutOfRangeException (
"decimal_number", decimal_number, "decimal_number - Too large") ;
}

for (int i = max; i < MAX_BIT; i++)
{
stringBuilder.Append(hexCharacters[remainders[i]]);
}

string s = stringBuilder.ToString();

int zero_padding_required = zero_padding - (MAX_BIT - max);

if (zero_padding_required > 0)
{
stringBuilder.Insert(0, new string('0', zero_padding_required));
}

s = stringBuilder.ToString();

if (isNegative)
{
stringBuilder.Insert(0, '-');
}

return stringBuilder.ToString();
}

_
modified on Tuesday, June 3, 2008 5:46 AM


Last Updated 28 May 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010