• 任意进制转换算法


    任意进制转换算法

    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

  • 相关阅读:
    linux下socket编程-TCP
    python正则表达式练习篇2
    python正则表达式练习篇
    python正则表达式基础篇
    Jmeter应用初步介绍
    数据库清除重复数据
    Nginx 获取真实 IP 方案
    Mac 实用工具bash-comletion介绍安装
    MySQL的binlog数据如何查看
    Mybatlis SQL 注入与防范
  • 原文地址:https://www.cnblogs.com/mq0036/p/7227997.html
Copyright © 2020-2023  润新知