任意进制转换算法
Posted jack_孟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了任意进制转换算法相关的知识,希望对你有一定的参考价值。
任意进制转换算法
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 |
十进制转十六进制表 ^ 19%16=3 | 0x3 19/16=1 | 0x1 = 0x13H
十六进制到二进制快速转换 <----------------------- 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
二进制到十六进制快速转换 <----------------------- 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
十进制快速转换十六进制 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
计算过程摆完了,下面是测试代码(代码未经优化,纯属测试):
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; } }
有趣的测试:
转换结果
代码未经测试,自己可以完善
http://www.cnblogs.com/Chinasf/p/5547968.html
以上是关于任意进制转换算法的主要内容,如果未能解决你的问题,请参考以下文章