Created
October 5, 2014 03:14
-
-
Save RobSeder/e5051341a51f163c04fd to your computer and use it in GitHub Desktop.
Radix calculator. Converts a value from one radix to another (from base-2 to base-36)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Interface for a class who converts a value from one radix to another. | |
/// </summary> | |
public interface IRadixCalculator | |
{ | |
/// <summary> | |
/// Converts a value from one base radix to another. | |
/// </summary> | |
/// <param name="value">The value to process. Can contain strings if they are | |
/// part of that base.</param> | |
/// <param name="sourceRadix">The radix which the <paramref name="value"/> is. 2 | |
/// through 36 allowed. (e.g. 10 for base-10, 16 for hexidecimal)</param> | |
/// <param name="destinationRadix">The radix to which to convert <paramref name="value"/>. | |
/// 2 through 36 allowed. (e.g. 10 for base-10, 16 for hexidecimal)</param> | |
/// <returns>The same value, but converted to the new radix.</returns> | |
/// <exception cref="ArgumentException">When <paramref name="value"/> is null or | |
/// empty.</exception> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source or destination radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new radix.</exception> | |
String CalculateRadix(String value, Int32 sourceRadix, Int32 destinationRadix); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Interface for a class who converts a string value to a number, and vice versa. | |
/// For example, converting the base-10 number 123456 into base-16 1E240 and back. | |
/// </summary> | |
/// <remarks>Code from: http://rosettacode.org/wiki/Non-decimal_radices/Convert </remarks> | |
public interface IStringAndNumberConverter | |
{ | |
/// <summary> | |
/// Converts a string to a number. | |
/// </summary> | |
/// <returns>The number representation of <paramref name="value"/>.</returns> | |
/// <param name="value">The string to convert.</param> | |
/// <param name="sourceRadix">The base, or radix of <paramref name="value"/> | |
/// (between 2 and 36).</param> | |
/// <exception cref="ArgumentException">When <paramref name="value"/> is null or | |
/// empty.</exception> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new value.</exception> | |
/// <remarks>Code from: http://rosettacode.org/wiki/Non-decimal_radices/Convert </remarks> | |
Int64 StringToLong(String value, Int32 sourceRadix); | |
/// <summary> | |
/// Converts a number to a string. | |
/// </summary> | |
/// <returns>The string representation of the value.</returns> | |
/// <param name="value">The number to convert.</param> | |
/// <param name="sourceRadix">The base, or radix of <paramref name="value"/> | |
/// (between 2 and 36).</param> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new value.</exception> | |
/// <remarks>Code from: http://rosettacode.org/wiki/Non-decimal_radices/Convert </remarks> | |
String LongToString(Int64 value, Int32 sourceRadix); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Class who converts a value from one radix to another. | |
/// </summary> | |
public class RadixCalculator : IRadixCalculator | |
{ | |
/// <summary> | |
/// Gets the current converter that will be used to convert numbers and | |
/// to strings and vice versa. | |
/// </summary> | |
public IStringAndNumberConverter Converter { get; protected set; } | |
/// <summary> | |
/// Creates a new instance of this type. | |
/// </summary> | |
/// <param name="converter">The converter to use.</param> | |
/// <exception cref="ArgumentNullException">When | |
/// <paramref name="converter"/> is null.</exception> | |
public RadixCalculator(IStringAndNumberConverter converter) | |
{ | |
if (converter == null) | |
throw new ArgumentNullException("converter"); | |
Converter = converter; | |
} | |
/// <summary> | |
/// Converts a value from one base radix to another. | |
/// </summary> | |
/// <param name="value">The value to process. Can contain strings if they are | |
/// part of that base.</param> | |
/// <param name="sourceRadix">The radix which the <paramref name="value"/> is. 2 | |
/// through 36 allowed. (e.g. 10 for base-10, 16 for hexidecimal)</param> | |
/// <param name="destinationRadix">The radix to which to convert <paramref name="value"/>. | |
/// 2 through 36 allowed. (e.g. 10 for base-10, 16 for hexidecimal)</param> | |
/// <returns>The same value, but converted to the new radix.</returns> | |
/// <exception cref="ArgumentException">When <paramref name="value"/> is null or | |
/// empty.</exception> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source or destination radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new radix.</exception> | |
public String CalculateRadix(String value, Int32 sourceRadix, Int32 destinationRadix) | |
{ | |
if (String.IsNullOrWhiteSpace(value)) | |
throw new ArgumentException("Argument \"value\" cannot be null or empty.", "value"); | |
if (sourceRadix < 2 || sourceRadix > 36) | |
throw new ArgumentOutOfRangeException("sourceRadix", "Argument \"sourceRadix\" must be between 2 and 36."); | |
if (destinationRadix < 2 || destinationRadix > 36) | |
throw new ArgumentOutOfRangeException("destinationRadix", "Argument \"destinationRadix\" must be between 2 and 36."); | |
Int64 numericResult = Converter.StringToLong(value, sourceRadix); | |
String stringResult = ProcessRadixConversion(destinationRadix, numericResult); | |
return stringResult; | |
} | |
private static String ProcessRadixConversion(Int32 destinationRadix, Int64 value) | |
{ | |
if (destinationRadix < 2 || destinationRadix > 36) | |
throw new ArgumentOutOfRangeException("destinationRadix", "Argument \"destinationRadix\" must be between 2 and 36."); | |
StringBuilder output = new StringBuilder(); | |
// Keep processing until we run out of things to process | |
while (value > 0) | |
{ | |
// We need to get the whole number by doing division | |
Int64 wholeNumber = value / destinationRadix; | |
// and the remainder by doing "mod" | |
Int64 remainder = (value % destinationRadix); | |
// We inject the remainder in the front of the value | |
if (remainder > 9) | |
{ | |
// We need to start using numbers for this value, so go back to zero | |
// and add 65, the decimal value for "A" | |
remainder = remainder - 10; | |
remainder = remainder + 65; // New starting place | |
output.Insert(0, (Char)remainder); | |
} | |
else | |
{ | |
output.Insert(0, remainder); | |
} | |
// Then process the whole number that is left. | |
value = wholeNumber; | |
} | |
// We've processed all the positions, return the converted output. | |
return output.ToString(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Class who converts a string value to a number, and vice versa. | |
/// For example, converting the base-10 number 123456 into base-16 1E240 and back. | |
/// </summary> | |
public class StringAndNumberConverter : IStringAndNumberConverter | |
{ | |
/// <summary> | |
/// Converts a string to a number. | |
/// </summary> | |
/// <returns>The number representation of <paramref name="value"/>.</returns> | |
/// <param name="value">The string to convert.</param> | |
/// <param name="sourceRadix">The base, or radix of <paramref name="value"/> | |
/// (between 2 and 36).</param> | |
/// <exception cref="ArgumentException">When <paramref name="value"/> is null or | |
/// empty.</exception> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new value.</exception> | |
/// <remarks>Code from: http://rosettacode.org/wiki/Non-decimal_radices/Convert </remarks> | |
public Int64 StringToLong(String value, Int32 sourceRadix) | |
{ | |
if (String.IsNullOrWhiteSpace(value)) | |
throw new ArgumentException("Argument \"value\" cannot be null or empty.", "value"); | |
if (sourceRadix < 2 || sourceRadix > 36) | |
throw new ArgumentOutOfRangeException("sourceRadix", "Argument \"sourceRadix\" must be between 2 and 36."); | |
checked | |
{ | |
Int32 valueLength = value.Length; | |
Int64 result = 0; | |
Boolean isNegative = false; | |
for (Int32 valueIndex = 0; valueIndex < valueLength; valueIndex++) | |
{ | |
Char c = value[valueIndex]; | |
Int32 num; | |
if (c == '-') | |
{ | |
if (valueIndex != 0) | |
throw new ArgumentException("Argument \"value\" may only have a negative sign as the first character of the string.", "value"); | |
isNegative = true; | |
continue; | |
} | |
if (c > 0x2F && c < 0x3A) | |
// Numeric character (subtract from 0x30 ('0') to get numerical value) | |
num = c - 0x30; | |
else if (c > 0x40 && c < 0x5B) | |
// Uppercase letter | |
// Subtract from 0x41 ('A'), then add 10 | |
num = c - 0x37; // 0x37 = 0x41 - 10 | |
else if (c > 0x60 && c < 0x7B) | |
// Lowercase letter | |
// Subtract from 0x61 ('a'), then add 10 | |
num = c - 0x57; // 0x57 = 0x61 - 10 | |
else | |
throw new ArgumentException("Argument \"value\" contains an invalid character '" + c + "'", "value"); | |
// Check that the digit is allowed by the base. | |
if (num >= sourceRadix) | |
throw new ArgumentException("Argument \"value\" contains a character '" + c + "' which is not allowed in base " + sourceRadix, "value"); | |
// Multiply the result by the base, then add the next digit | |
result *= sourceRadix; | |
result += num; | |
} | |
if (isNegative) | |
result = -result; | |
return result; | |
} | |
} | |
/// <summary> | |
/// Converts a number to a string. | |
/// </summary> | |
/// <returns>The string representation of the value.</returns> | |
/// <param name="value">The number to convert.</param> | |
/// <param name="sourceRadix">The base, or radix of <paramref name="value"/> | |
/// (between 2 and 36).</param> | |
/// <exception cref="ArgumentOutOfRangeException">When <paramref name="value"/> | |
/// contains a character which is out of range. (e.g. having an "A" in a base-10 | |
/// value) of if the source radix is less than 2 or greater than 36.</exception> | |
/// <exception cref="InvalidOperationException">When there was an error calculating | |
/// the new value.</exception> | |
/// <remarks>Code from: http://rosettacode.org/wiki/Non-decimal_radices/Convert </remarks> | |
public String LongToString(Int64 value, Int32 sourceRadix) | |
{ | |
if (sourceRadix < 2 || sourceRadix > 36) | |
throw new ArgumentOutOfRangeException("sourceRadix", "Argument \"sourceRadix\" must be between 2 and 36."); | |
if (sourceRadix == 10) | |
return value.ToString(); | |
checked | |
{ | |
Int64 longBase = sourceRadix; | |
StringBuilder output = new StringBuilder(); | |
if (value < 0) | |
{ | |
value = -value; | |
output.Append('-'); | |
} | |
Int64 div = 1; | |
while (value/div >= sourceRadix) | |
{ | |
// Continue multiplying the dividend by the base until it reaches the greatest power of | |
// the base which is less than or equal to the number. | |
div *= sourceRadix; | |
} | |
while (true) | |
{ | |
Byte digit = (Byte)(value / div); | |
if (digit < 10) | |
// Numeric character (0x30 = '0') | |
output.Append((char)(digit + 0x30)); | |
else | |
// Alphabetic character (for digits > 10) (0x61 = 'a') | |
output.Append((char)(digit + 0x57)); // 0x61 - 10 | |
if (div == 1) | |
// Stop when the dividend reaches 1 | |
break; | |
value %= div; | |
div /= sourceRadix; | |
} | |
return output.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment