任意進位轉換演算法

来源:http://www.cnblogs.com/Chinasf/archive/2016/05/31/5547968.html
-Advertisement-
Play Games

N年沒有寫博客,發個進位轉換的玩下,支持負數;功能屬於簡化版的 Convert.ToInt32 ,特點是: 1、任意位,如:0,1(二進位),0...7(八進位),0...9,A...F(16進位),0...N(N進位),或者是:!@#$%^&*(8進位,字元符號),也可以是中文。 2、8 byte ...


任意進位轉換演算法

N年沒有寫博客,發個進位轉換的玩下,支持負數;功能屬於簡化版的 Convert.ToInt32 ,特點是:

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

2、8 位最大長度。

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)
        {
            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;
        }
    }

 

有趣的測試:

轉換結果

 

代碼未經測試,自己可以完善


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 引導工具GRUB詳解 引導工具GRUB詳解 引導工具GRUB詳解 導讀 引導程式是駐留在硬碟第一個扇區(MPR、主引導記錄)的程式。GRUB是一個功能強大的多系統引導程式,專門處理Linux與其它操作系統共存的問題。下麵就由我介紹一下grub.conf文件里的具體內容及其含義。 使用一下命令可以查看 ...
  • 人們對決策樹的使用 決策樹常常被應用於數據挖掘之中,是最基礎的演算法之一,幾乎每一個學習過數據挖掘的朋友都知道決策樹。但還原決策樹本來的用途,它被用於一些決策或決定時,還是比較實用和直觀的。其樹型結構指導人們進行在面對某個決策時,先關註其中幾個最重要的方向,這幾方向定下來後,再細分下去。近年來泳道路, ...
  • 公司產品中一直是採用 flash 實現文件上傳功能,但用戶的需求多了以後遇到了越來越多難以解決的問題,最後試著用碩正提供的freeform、小型頁面控制項來解決。 碩正文件上傳的實現途徑有3、4種,由於公司產品發佈的需要,就選擇了其中的 httpPost 方案,其它的象 ftp、Http put儘管也 ...
  • MSDN中的描述: Visual Studio 項目對程式的發佈和調試版本分別有單獨的配置。顧名思義,生成調試版本的目的是用於調試,而生成發佈版本的目的是用於版本的最終分發。 如果在 Visual Studio 中創建程式,Visual Studio 將自動創建這些配置並設置適當的預設選項和其他設置 ...
  • 概述 當方法返回類型或屬性類型為集合時,有些開發者會千篇一律地使用IList集合。然而IList具有集合的所有操作,這意味著調用者不僅可以讀取集合信息,還能夠修改集合。業務需求本來只是為調用者提供一個可讀的集合,例如數據的查詢和展示,但當方法返回IList時,無疑隱式地開放了集合可寫的許可權。此時,我... ...
  • 之前由於剛入行不久,對數據持久化不是很瞭解,尤其是用資料庫存儲大量數據的操作。經過摸索就在此總結一下,方便以後查閱 下麵就簡單介紹一下: 1.NSUserDefaults 感覺最常用的小量數據,屬性,例如,賬號,密碼之類的;適合存儲輕量級的本地數據 (個人認為這種比較簡單) NSUserDefaul ...
  • 前面學起來還是很順的,畢竟很多都接觸過。 後面學起來只能用“磨”來形容,以至於八章用了2個月。(當然也有相當一些原因是這兩個月中發生了一些個人生活上的問題) 總的來說收穫超大,這種感覺就像大一的時候學習老譚的C語言一樣,醍醐灌頂。 如果是靠.NET吃飯的人,不讀這本書真的是太可惜了。 不過這中間也出 ...
  • 上一章講了基元線程同步構造,而其它的線程同步構造都是基於這些基元線程同步構造的,並且一般都合併了用戶模式和內核模式構造,我們稱之為混合線程同步構造。 在沒有線程競爭時,混合線程提供了基於用戶模式構造所具備的性能優勢,而多個線程競爭一個構造時,混合線程通過基元內核模式的構造來提供不“自旋”的優勢。 那 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...