-
Notifications
You must be signed in to change notification settings - Fork 292
/
BaseConversion.cs
113 lines (95 loc) · 3.81 KB
/
BaseConversion.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using System;
using System.Text;
namespace Advanced.Algorithms.Binary;
/// <summary>
/// Base conversion implementation.
/// </summary>
public class BaseConversion
{
/// <summary>
/// Converts base of given number to the target base.
/// </summary>
/// <param name="srcNumber">Input number in source base system.</param>
/// <param name="srcBaseChars">Source base system characters in increasing order. For example 0123456789 for base 10.</param>
/// <param name="dstBaseChars">Destination base system characters in increasing order. For example 01 for base 2.</param>
/// <param name="precision">Required precision when dealing with fractions. Defaults to 32 places.</param>
/// <returns>The result in target base as a string.</returns>
public static string Convert(string srcNumber,
string srcBaseChars,
string dstBaseChars, int precision = 32)
{
srcNumber = srcNumber.Trim();
if (srcNumber.Contains("."))
{
var tmp = srcNumber.Split('.');
var whole = tmp[0].TrimEnd();
var fraction = tmp[1].TrimStart();
return ConvertWhole(whole, srcBaseChars, dstBaseChars) +
"." + ConvertFraction(fraction, srcBaseChars, dstBaseChars, precision);
}
return ConvertWhole(srcNumber, srcBaseChars, dstBaseChars);
}
/// <summary>
/// Converts the whole part of source number.
/// </summary>
private static string ConvertWhole(string srcNumber,
string srcBaseChars,
string dstBaseChars)
{
if (string.IsNullOrEmpty(srcNumber)) return string.Empty;
var srcBase = srcBaseChars.Length;
var dstBase = dstBaseChars.Length;
if (srcBase <= 1) throw new Exception("Invalid source base length.");
if (dstBase <= 1) throw new Exception("Invalid destination base length.");
long base10Result = 0;
var j = 0;
//convert to base 10
//move from least to most significant numbers
for (var i = srcNumber.Length - 1; i >= 0; i--)
{
//eg. 1 * 2^0
base10Result += srcBaseChars.IndexOf(srcNumber[i])
* (long)Math.Pow(srcBase, j);
j++;
}
var result = new StringBuilder();
//now convert to target base
while (base10Result != 0)
{
var rem = (int)base10Result % dstBase;
result.Insert(0, dstBaseChars[rem]);
base10Result = base10Result / dstBase;
}
return result.ToString();
}
/// <summary>
/// Converts the fractional part of source number.
/// </summary>
private static string ConvertFraction(string srcNumber,
string srcBaseChars,
string dstBaseChars, int maxPrecision)
{
if (string.IsNullOrEmpty(srcNumber)) return string.Empty;
var srcBase = srcBaseChars.Length;
var dstBase = dstBaseChars.Length;
if (srcBase <= 1) throw new Exception("Invalid source base length.");
if (dstBase <= 1) throw new Exception("Invalid destination base length.");
decimal base10Result = 0;
//convert to base 10
//move from most significant numbers to least
for (var i = 0; i < srcNumber.Length; i++)
//eg. 1 * 1/(2^1)
base10Result += srcBaseChars.IndexOf(srcNumber[i])
* (decimal)(1 / Math.Pow(srcBase, i + 1));
var result = new StringBuilder();
//now convert to target base
while (base10Result != 0 && maxPrecision > 0)
{
base10Result = base10Result * dstBase;
result.Append(dstBaseChars[(int)Math.Floor(base10Result)]);
base10Result -= Math.Floor(base10Result);
maxPrecision--;
}
return result.ToString();
}
}