任意进制转换算法


N年没有写博客,发个进制转换的玩下,支持负数;功能属于简化版的 Convert.ToInt32 ,特点是:

1、任意位,如:0,1(二进制),0...7(八进制),0...9,A...F(16进制),0...N(N进制),或者是:!@#$%^&*(8进制,字符符号),也可以是中文。

2、8 位最大长度。

3、C#源码。

最近写markdown格式习惯啦,cnblogs啥时候全改掉算了,别用这个htmleditor算了。

先说明下进制转换的基础知识,不会的可以了解下,会的就别看了,后面的也别看,纯粹属于浪费时间。

 





​​



1


2


3


4


5


6


7


8


9


10


11


12




​十六进制转十进制表​


 


​10         15        1​


​<--------------------------------------------------------------------​


​0         0         0        0      0      A         F         1​


​<--------------------------------------------------------------------​


​16^7       16^6      16^5     16^4   16^3  16^2       16^1      16^0​


​268435456  16777216  1048576  65536  4096  256        16        1​


​<--------------------------------------------------------------------​


​(10*256) + (15*16) + (1*1)​


​=2560+240+1​


​=2801​



  



任意进制转换算法_i++

十进制转十六进制表

^
19%16=3 | 0x3
19/16=1 | 0x1
= 0x13H


任意进制转换算法_进制转换_02


 



任意进制转换算法_十进制_03

十六进制到二进制快速转换

<-----------------------
2^3 2^2 2^1 2^0
8 4 2 1
<-----------------------
0xF821 = 1111 1000 0010 0001
<-----------------------
0xF = 15
= 8 + 4 + 2 + 1
= 1 1 1 1
0x8 = 8
= 8 + 0 + 0 + 0
= 1 0 0 0
0x2 = 2
= 0 + 0 + 2 + 0
= 0 0 1 0
0x1 = 1
= 0 + 0 + 0 + 1
= 0 0 0 1


任意进制转换算法_十六进制_04


 



任意进制转换算法_十进制_05

二进制到十六进制快速转换
<-----------------------
2^3 2^2 2^1 2^0
8 4 2 1
<-----------------------
1111 1000 0010 0001 = 0xF821
<-----------------------
1111 = 8 + 4 + 2 + 1
= 15
= 0xF
1000 = 8 + 0 + 0 + 0
= 8
= 0x8
0010 = 0 + 0 + 2 + 0
= 2
= 0x2
0001 = 0 + 0 + 0 + 1
= 1
= 0x1


任意进制转换算法_i++_06


 



任意进制转换算法_十六进制_07

十进制快速转换十六进制
103 = (6 * 16) + 7 = 0x67
22 = (1 * 16) + 6 = 0x16
54 = (3 * 16) + 6 = 0x36
255 = (15* 16) + 15 = 0xff
999 = (62 * 16) + 7 ~ 0x7
62= (3 * 16) + 14 ~ 0xe
= 3 ~ 0x3
= 0x3e7
9999= (624 * 16) + 15 ~ 0xF
624= (39*16) + 0 ~ 0x0
39= (2* 16) + 7 ~ 0x7
2= 2 ~ 0x2
= 0x270f
1980= (123 * 16) + 12 ~ 0xc
123= (7 * 16) + 11 ~ 0xb
7= 7 ~ 0x7
= 0x7bc


任意进制转换算法_进制转换_08


 

计算过程摆完了,下面是测试代码(代码未经优化,纯属测试):



任意进制转换算法_i++_09

class MainClass
{
public static void Main (string[] args)
{
var nt = -3212;
var ct = "";
ct = ConvertToAny (nt, 0, "a,b,c");
Console.WriteLine (ct);
var rt = AnyToNumber (ct, "a,b,c");
Console.WriteLine (rt);
Console.WriteLine (Convert.ToString(nt,2));
Console.ReadLine ();

Console.WriteLine ("Test begin");
for (int n = -1230; n < 1230; n++) {
var a = n.ToString ("X");
var b = ConvertToAny (n, 0, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
if (a != b) {
Console.WriteLine ("[{2}]Error:a!=b: {0} {1}", a, b, n);
} else if (n % 100 == 0) {
Console.WriteLine ("[{2}]Curr: a!=b: {0} {1} OK", a, b, n);
}
}
Console.WriteLine ("Test ok");

Console.WriteLine ("Test begin");
for (int n = -1230; n < 1230; n++) {
var hex = n.ToString ("X");
var a = Convert.ToInt32 (hex, 16);
var b = AnyToNumber (hex, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
if (a != b) {
Console.WriteLine ("[{2}]Error:a!=b: {0} {1}", a, b, hex);
} else if (n % 100 == 0) {
Console.WriteLine ("[{2}]Curr: a!=b: {0} {1} OK", a, b, hex);
}
}
Console.WriteLine ("Test ok");
Console.WriteLine (ConvertToAny (int.MaxValue, 0, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F"));
}

static bool isNegativeNumber(string any, string anyString ){
var s = ConvertToAny (int.MaxValue, 0, anyString);
if (s.Length != any.Length) {
return false;
} else {

var ReverseTable = BuildReverseTable (anyString);

if (ReverseTable [any [0].ToString ()] > ReverseTable [s [0].ToString ()]) {
return true;
}
}
return false;
}
static int AnyToNumber (string any, string anyString = "0,1,2,3,4,5,6,7,8,9")
{
int sum = 0;
var ConversionTable = BuildConversionTable (anyString);
var ReverseTable = BuildReverseTable (anyString);
var tableBit = ConversionTable.Count;

bool negativeNumber = false;
var conversionPadSize = 0;
conversionPadSize = 128 / tableBit;
if (tableBit < 10) {
conversionPadSize /= 2;
}
//是否负数
if( isNegativeNumber( any, anyString) ){
negativeNumber = true;
//反转
var res = any;
any = "";
var moveBit = tableBit - 1;
foreach (var c in res) {
any += NumberConversion (ConversionTable, moveBit - FindConversion (ReverseTable, c.ToString ()));
}
}
var cur = any.Length - 1;
for (var n = 0; n < any.Length; n++,cur--) {
var c = any [n].ToString ();

var bitSum = FindConversion (ReverseTable, c) * (int)Math.Pow (tableBit, cur);
sum += bitSum;
}
if (negativeNumber) {
//补位
sum++;
sum = 0 - sum;
}
return sum;
}

static string ConvertToAny (int number, int padSize = 8, string anyString = "0,1,2,3,4,5,6,7,8,9")
{
var conversionPadSize = padSize;

var ConversionTable = BuildConversionTable (anyString);
var ReverseTable = BuildReverseTable (anyString);
var tableBit = ConversionTable.Count;

long input = Math.Abs ((long)number);
//补码
if (number < 0) {
input -= 1;

conversionPadSize = 128 / tableBit;
if (tableBit < 10) {
conversionPadSize /= 2;
}
}

var result = "";
while (true) {
if (input >= tableBit) {
result = NumberConversion (ConversionTable, (int)(input % tableBit)) + result;
input = (int)(input / tableBit);
} else {
result = NumberConversion (ConversionTable, (int)input) + result;
break;
}
}

if (result.Length < conversionPadSize) {
//补位
result = StringPadLeft (result, conversionPadSize, ConversionTable [0]);
} else {
// //对齐
// if (result.Length % 2 != 0) {
// result = ConversionTable[0] + result;
// }
}

if (number < 0) {
//反转
var res = result;
result = "";
var moveBit = tableBit - 1;
foreach (var c in res) {
result += NumberConversion (ConversionTable, moveBit - FindConversion (ReverseTable, c.ToString ()));
}
}

return result;
}

static string StringPadLeft (string src, int size, string c)
{
var nsize = size - src.Length;
for (var n = 0; n < nsize; n++) {
src = c + src;
}
return src;
}

static string NumberConversion (Dictionary<int,string> table, int n)
{
return table [n];
}

static int FindConversion (Dictionary<string,int> table, string c)
{
return table [c];
}

static Dictionary<string,int> BuildReverseTable (string tableString)
{
var table = tableString.Split (",".ToCharArray (), StringSplitOptions.RemoveEmptyEntries).ToList ();
//补位操作,必须是2的倍数
if (table.Count % 2 != 0) {
table.Insert (0, "0");
}
var result = new Dictionary<string,int> ();
for (var i = 0; i < table.Count; i++) {
result.Add (table [i].ToString (), i);
}
return result;
}

static Dictionary<int,string> BuildConversionTable (string tableString)
{
var table = tableString.Split (",".ToCharArray (), StringSplitOptions.RemoveEmptyEntries).ToList ();
//补位操作,必须是2的倍数
if (table.Count % 2 != 0) {
table.Insert (0, "0");
}
var result = new Dictionary<int,string> ();
for (var i = 0; i < table.Count; i++) {
result.Add (i, table [i].ToString ());
}
return result;
}
}


任意进制转换算法_i++_10


 

有趣的测试:

任意进制转换算法_进制转换_11

转换结果

任意进制转换算法_i++_12

 

代码未经测试,自己可以完善


 

 



任意进制转换算法


N年没有写博客,发个进制转换的玩下,支持负数;功能属于简化版的 Convert.ToInt32 ,特点是:

1、任意位,如:0,1(二进制),0...7(八进制),0...9,A...F(16进制),0...N(N进制),或者是:!@#$%^&*(8进制,字符符号),也可以是中文。

2、8 位最大长度。

3、C#源码。

最近写markdown格式习惯啦,cnblogs啥时候全改掉算了,别用这个htmleditor算了。

先说明下进制转换的基础知识,不会的可以了解下,会的就别看了,后面的也别看,纯粹属于浪费时间。

 





​​



1


2


3


4


5


6


7


8


9


10


11


12




​十六进制转十进制表​


 


​10         15        1​


​<--------------------------------------------------------------------​


​0         0         0        0      0      A         F         1​


​<--------------------------------------------------------------------​


​16^7       16^6      16^5     16^4   16^3  16^2       16^1      16^0​


​268435456  16777216  1048576  65536  4096  256        16        1​


​<--------------------------------------------------------------------​


​(10*256) + (15*16) + (1*1)​


​=2560+240+1​


​=2801​



  



任意进制转换算法_i++_13

十进制转十六进制表

^
19%16=3 | 0x3
19/16=1 | 0x1
= 0x13H


任意进制转换算法_进制_14


 



任意进制转换算法_十进制_15

十六进制到二进制快速转换

<-----------------------
2^3 2^2 2^1 2^0
8 4 2 1
<-----------------------
0xF821 = 1111 1000 0010 0001
<-----------------------
0xF = 15
= 8 + 4 + 2 + 1
= 1 1 1 1
0x8 = 8
= 8 + 0 + 0 + 0
= 1 0 0 0
0x2 = 2
= 0 + 0 + 2 + 0
= 0 0 1 0
0x1 = 1
= 0 + 0 + 0 + 1
= 0 0 0 1


任意进制转换算法_十进制_16


 



任意进制转换算法_进制_17

二进制到十六进制快速转换
<-----------------------
2^3 2^2 2^1 2^0
8 4 2 1
<-----------------------
1111 1000 0010 0001 = 0xF821
<-----------------------
1111 = 8 + 4 + 2 + 1
= 15
= 0xF
1000 = 8 + 0 + 0 + 0
= 8
= 0x8
0010 = 0 + 0 + 2 + 0
= 2
= 0x2
0001 = 0 + 0 + 0 + 1
= 1
= 0x1


任意进制转换算法_十六进制_18


 



任意进制转换算法_进制转换_19

十进制快速转换十六进制
103 = (6 * 16) + 7 = 0x67
22 = (1 * 16) + 6 = 0x16
54 = (3 * 16) + 6 = 0x36
255 = (15* 16) + 15 = 0xff
999 = (62 * 16) + 7 ~ 0x7
62= (3 * 16) + 14 ~ 0xe
= 3 ~ 0x3
= 0x3e7
9999= (624 * 16) + 15 ~ 0xF
624= (39*16) + 0 ~ 0x0
39= (2* 16) + 7 ~ 0x7
2= 2 ~ 0x2
= 0x270f
1980= (123 * 16) + 12 ~ 0xc
123= (7 * 16) + 11 ~ 0xb
7= 7 ~ 0x7
= 0x7bc


任意进制转换算法_十六进制_20


 

计算过程摆完了,下面是测试代码(代码未经优化,纯属测试):



任意进制转换算法_十进制_21

class MainClass
{
public static void Main (string[] args)
{
var nt = -3212;
var ct = "";
ct = ConvertToAny (nt, 0, "a,b,c");
Console.WriteLine (ct);
var rt = AnyToNumber (ct, "a,b,c");
Console.WriteLine (rt);
Console.WriteLine (Convert.ToString(nt,2));
Console.ReadLine ();

Console.WriteLine ("Test begin");
for (int n = -1230; n < 1230; n++) {
var a = n.ToString ("X");
var b = ConvertToAny (n, 0, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
if (a != b) {
Console.WriteLine ("[{2}]Error:a!=b: {0} {1}", a, b, n);
} else if (n % 100 == 0) {
Console.WriteLine ("[{2}]Curr: a!=b: {0} {1} OK", a, b, n);
}
}
Console.WriteLine ("Test ok");

Console.WriteLine ("Test begin");
for (int n = -1230; n < 1230; n++) {
var hex = n.ToString ("X");
var a = Convert.ToInt32 (hex, 16);
var b = AnyToNumber (hex, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
if (a != b) {
Console.WriteLine ("[{2}]Error:a!=b: {0} {1}", a, b, hex);
} else if (n % 100 == 0) {
Console.WriteLine ("[{2}]Curr: a!=b: {0} {1} OK", a, b, hex);
}
}
Console.WriteLine ("Test ok");
Console.WriteLine (ConvertToAny (int.MaxValue, 0, "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F"));
}

static bool isNegativeNumber(string any, string anyString ){
var s = ConvertToAny (int.MaxValue, 0, anyString);
if (s.Length != any.Length) {
return false;
} else {

var ReverseTable = BuildReverseTable (anyString);

if (ReverseTable [any [0].ToString ()] > ReverseTable [s [0].ToString ()]) {
return true;
}
}
return false;
}
static int AnyToNumber (string any, string anyString = "0,1,2,3,4,5,6,7,8,9")
{
int sum = 0;
var ConversionTable = BuildConversionTable (anyString);
var ReverseTable = BuildReverseTable (anyString);
var tableBit = ConversionTable.Count;

bool negativeNumber = false;
var conversionPadSize = 0;
conversionPadSize = 128 / tableBit;
if (tableBit < 10) {
conversionPadSize /= 2;
}
//是否负数
if( isNegativeNumber( any, anyString) ){
negativeNumber = true;
//反转
var res = any;
any = "";
var moveBit = tableBit - 1;
foreach (var c in res) {
any += NumberConversion (ConversionTable, moveBit - FindConversion (ReverseTable, c.ToString ()));
}
}
var cur = any.Length - 1;
for (var n = 0; n < any.Length; n++,cur--) {
var c = any [n].ToString ();

var bitSum = FindConversion (ReverseTable, c) * (int)Math.Pow (tableBit, cur);
sum += bitSum;
}
if (negativeNumber) {
//补位
sum++;
sum = 0 - sum;
}
return sum;
}

static string ConvertToAny (int number, int padSize = 8, string anyString = "0,1,2,3,4,5,6,7,8,9")
{
var conversionPadSize = padSize;

var ConversionTable = BuildConversionTable (anyString);
var ReverseTable = BuildReverseTable (anyString);
var tableBit = ConversionTable.Count;

long input = Math.Abs ((long)number);
//补码
if (number < 0) {
input -= 1;

conversionPadSize = 128 / tableBit;
if (tableBit < 10) {
conversionPadSize /= 2;
}
}

var result = "";
while (true) {
if (input >= tableBit) {
result = NumberConversion (ConversionTable, (int)(input % tableBit)) + result;
input = (int)(input / tableBit);
} else {
result = NumberConversion (ConversionTable, (int)input) + result;
break;
}
}

if (result.Length < conversionPadSize) {
//补位
result = StringPadLeft (result, conversionPadSize, ConversionTable [0]);
} else {
// //对齐
// if (result.Length % 2 != 0) {
// result = ConversionTable[0] + result;
// }
}

if (number < 0) {
//反转
var res = result;
result = "";
var moveBit = tableBit - 1;
foreach (var c in res) {
result += NumberConversion (ConversionTable, moveBit - FindConversion (ReverseTable, c.ToString ()));
}
}

return result;
}

static string StringPadLeft (string src, int size, string c)
{
var nsize = size - src.Length;
for (var n = 0; n < nsize; n++) {
src = c + src;
}
return src;
}

static string NumberConversion (Dictionary<int,string> table, int n)
{
return table [n];
}

static int FindConversion (Dictionary<string,int> table, string c)
{
return table [c];
}

static Dictionary<string,int> BuildReverseTable (string tableString)
{
var table = tableString.Split (",".ToCharArray (), StringSplitOptions.RemoveEmptyEntries).ToList ();
//补位操作,必须是2的倍数
if (table.Count % 2 != 0) {
table.Insert (0, "0");
}
var result = new Dictionary<string,int> ();
for (var i = 0; i < table.Count; i++) {
result.Add (table [i].ToString (), i);
}
return result;
}

static Dictionary<int,string> BuildConversionTable (string tableString)
{
var table = tableString.Split (",".ToCharArray (), StringSplitOptions.RemoveEmptyEntries).ToList ();
//补位操作,必须是2的倍数
if (table.Count % 2 != 0) {
table.Insert (0, "0");
}
var result = new Dictionary<int,string> ();
for (var i = 0; i < table.Count; i++) {
result.Add (i, table [i].ToString ());
}
return result;
}
}


任意进制转换算法_进制_22


 

有趣的测试:

任意进制转换算法_进制转换_11

转换结果

任意进制转换算法_i++_12

 

代码未经测试,自己可以完善