任意进制转换算法

任意进制转换算法

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

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

2、8 byte 最大长度。

3、C#源码。

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

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

 十六进制转十进制表

                                           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)
        {
            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 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;
            if (any.Length == 8 && any [0] > ‘7‘) {
                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);

            long input = Math.Abs ((long)number);
            //补码
            if (number < 0) {
                input -= 1;
                conversionPadSize = sizeof(int) * 2;
            }

            var result = "";
            var tableBit = ConversionTable.Count;
            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 = result.PadLeft (conversionPadSize, ‘0‘);
            }
//            else {
//                //对齐
//                if (result.Length % 2 != 0) {
//                    result = ‘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 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);
            var result = new Dictionary<string,int> ();
            for (var i = 0; i < table.Length; i++) {
                result.Add (table [i].ToString (), i);
            }
            return result;
        }

        static Dictionary<int,string> BuildConversionTable (string tableString)
        {
            var table = tableString.Split (",".ToCharArray (), StringSplitOptions.RemoveEmptyEntries);
            var result = new Dictionary<int,string> ();
            for (var i = 0; i < table.Length; i++) {
                result.Add (i, table [i].ToString ());
            }
            return result;
        }
    }

有趣的测试:

转换结果

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

时间: 2024-12-03 00:03:37

任意进制转换算法的相关文章

lua之m进制转换为n进制-任意进制转换算法

够无聊的写这个,为防止需要的人也无聊一遍,写个吧 算法有n种,但是,咱们一种就够用了 1 --数组倒序排列 2 local function orderByDesc( input ) 3 local output = {} 4 local count = #input 5 while count > 0 do 6 table.insert(output, input[count] ) 7 count = count -1 8 end 9 return output 10 end 11 12 --

Python版任意进制转换

def decimalToAny(num,n): baseStr = {10:"a",11:"b",12:"c",13:"d",14:"e",15:"f",16:"g",17:"h",18:"i",19:"j"} new_num_str = "" while num != 0: remai

2~62位任意进制转换(c++)

进制转换的符号表为[0-9a-zA-Z],共61个字符,最大可表示62进制. 思路是原进制先转换为10进制,再转换到目标进制. 疑问: 对于负数,有小伙伴说可以直接将符号丢弃,按照整数进行进位转换,最后再将负号补回来,我认为这种做法是不对的. 正确的做法是:考虑好按照16位(short)还是32位(int)抑或64位(long long),先求出二进制补码(这时候就正负数就统一了),将二进制数转换为十进制后在转换为其他进制(如果有小伙伴知道如何直接将二进制转换为任意进制的方法可以留言告诉我,不胜

【ACM】大数据+任意进制转换 jobdu 1080

[九度OJ] 1080 进制转换 题目描述: 将M进制的数X转换为N进制的数输出. 输入: 输入的第一行包括两个整数:M和N(2<=M,N<=36).下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数输出. 输出: 输出X的N进制表示的数. 样例输入: 16 10 F 样例输出: 15 提示: 输入时字母部分为大写,输出时为小写,并且有大数据. 这题考察的比较综合,进制转换+大数据 很久没有做ACM的题目了,且拿这个练练手,大整数模板是用的王道论坛的模板-贴出来备

c语言将字符串转成int,将int转成字符串。附带任意进制转换函数

在网上看到各种将字符串转成int,和int转成字符串的方法.我自己比较喜欢用的方法是下面的,记住模板就行,最开始我也老是记不住,找到规律,多用几遍就好了. 1.将字符串转成int char s[20] = "123456";   // 注如果此处不是数字字符串类型,如下面的字符串  12abc -->  12        ab12 --> 0 int a = 0; sscanf(s,"%d",&a);   // a = 123456   就得到

任意进制转换简单理解

规则1:任意进制转10进制都是当前位数乘以当前位权重 规则2:N进制转M进制根据前值除/M的值,然后取M进制余数为当前位,小数位就是后乘取整;(基本就是这个思想) 首先,实现任意进制转其他进制,最好先转到10进制在操作比较方便; 目前代码只实现10->36 思想是一样的使用递归计算- -改变除数(/N)和求的余数(/M),然后根据逻辑值对应字符表示就是- -,楼主目前不知道Z以上怎么表示- -所以懵 1 #include <iostream> 2 3 4 void turnto36(in

【模板小程序】2~62位非负数任意进制转换,包含合法性检查

1 //进制转换模块 2 #include <iostream> 3 #include <string> 4 #include <cmath> 5 #include <algorithm> 6 7 using namespace std; 8 9 //将任意字符转换为十进制 [0-9a-zA-Z],61个字符,最大表示62进制 10 int convertToDec(char c) 11 { 12 int decNum; 13 if(c>='0' &a

进制转换算法的C语言实现

         进制问题几乎是刚入门计算机时学的东西,即便如此,你知道进制之间是如何转换的吗?下面就来详细说明各进制之间的转换原理. (一)二.八.十六进制转十进制 2.8.16转10有一个通用的算法,就是用各位上的数乘以本进制的基数的n次幂(n为本位数后面的位数)求值后相加所得.有点绕口是吧?语文没学好,请谅解,下面举个例就懂了. Eg:100002=? 10 这是将二进制的10000转换成十进制,从左往右看,第一位是1,后面位数都是0,那就是: 1*24+0*23+0*22+0*21+0*

任意进制转换

#include<iostream> #include<cstdio> using namespace std; int main() { int n,m,k=0,a,x,c,i,b[100],y; char s[36]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T' ,'U','V','W