MyException - 我的异常网
当前位置:我的异常网» C# » 自个儿实现各种进制相互转换

自个儿实现各种进制相互转换

www.MyException.Cn  网友分享于:2015-08-20  浏览:0次
自己实现各种进制相互转换

本文自己实现了2、8、10、16进制数的相互转换。实际中很少用到或者直接用api,所以大神老鸟请绕行。

有兴趣的朋友也可以自己先写写,当做练习,仅此而已。

ok, 直接进入主题。先说一下各进制转换的算法(百度一下也ok的)。

 

算法:

一、10 进制数是平时所用到的,先从它开始。10进制转换为其它进制的数,用到的是【辗转相除取余法】。简单的说,就是该数一直除以进制数(例如2进制就除以2),然后取余数,一直到结果为0。依次由下往上取余数就是结果。

例如:5(10进制),转换为2进制,进行上述过程,得到的余数分别是:1、0、1, 那么结果就是:101(二进制)。对于 8和16进制,也是同样的过程。需要注意的是,对于16进制,10-15 分别表示为:A-E。

二、非10进制转换为10进制数。用到的是【位乘法】(名称是乱起的,只是为了与除法相对)。简单的说,公式就是:i * base^(j-1),i: 第j位上的数, base:进制  j: 第j位。例如:101(2进制),运用公式后就是:1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 5(十进制)。

三、其它进制的相互转换。既然有了10进制这个“中间人”,其它的转换只要通过这个中间人就可以了。实际上转换的过程也很简单,例如8进制转2进制,就是“一分为三”;16进制转2进制,就是“一分为四”;相反的过程就是“三位合一”、“四位合一”。

需要注意的是:上述计算过程都是针对整数部分,如果是小数部分,计算就不一样了。

现在我们来看看小数部分的计算。

对于一、小数部分的计算是:小数部分 * base 取整数,小数部分再继续 * base,再得到整数... 一直到小数部分为0。例如10进制数:0.5,转为8进制是:

0.5 * 8 = 4.0 ; 也就是:4。

对于二、小数部分的计算是:i * base^(-j)。 例如2进制数,0.11,小数部分的计算是:1 * 2^(-1) + 1 * 2^(-2)。

 so,上面就是基本的转换过程,文字表达起来肯定没那么清晰,有兴趣的朋友可以百度,图文并茂,更好理解。

 

实现:

我们先来看一下利用.net提供的功能是如何实现的,很简单,就2行代码,如下:

static string SystemConvertUseAPI(string value, int from, int to)
{
    int temp = Convert.ToInt32(value, from);
    return Convert.ToString(temp, to);
}

不过Convert自带的转换有一个缺点,就是无法计算小数和负数,.net3.5 下测试的,不知道高版本的可不可以。

下面是我自己的实现过程,(核心部分就是与10进制的相互转换),如下:

    public static class SystemConvert
    {
        public static string ConvertValue(string value, int from, int to)
        {
            EnsureArguments(value, from, to);
            char c = value[0];
            string[] values = GetValues(value);
            string result = string.Empty;
            if (from == 10)
                result = TenToOthers(values, to);
            else if (to == 10)
                result = OthersToTen(values, from);
            else
                result = OthersToOthers(values, from, to);

            return c == '-' ? c.ToString() + result : result;
        }

        /// <summary>
        /// 检查参数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        private static void EnsureArguments(string value, int from, int to)
        {
            if (value == null || value.Trim() == string.Empty)
                throw new ArgumentNullException("value");
            if (!(from == 10 || from == 2 || from == 8 || from == 16))
                throw new ArgumentException("from 指定的基数不正确!");
            if (!(to == 10 || to == 2 || to == 8 || to == 16))
                throw new ArgumentException("to 指定的基数不正确!");

            string pattern = string.Empty;
            Regex regex = null;
            if (from == 2)
                pattern = @"^(\-|\+?)[01]+(.{0,1}[01]+)?$";
            else if (from == 8)
                pattern = @"^(\-|\+?)[01234567]+(.{0,1}[01234567]+)?$";
            else if (from == 10)
                pattern = @"^(\-|\+?)[0123456789]+(.{0,1}[0123456789]+)?$";
            else
                pattern = @"^(\-|\+?)[0123456789|abcdef|ABCDEF]+(.{0,1}[0123456789|abcdef|ABCDEF]+)?$";

            regex = new Regex(pattern);
            if (!regex.IsMatch(value))
                throw new ArgumentException("源字符串不符合" + from.ToString() + "进制规范");
        }

        /// <summary>
        /// 拆分字符串
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string[] GetValues(string value)
        {
            value = value.Trim(new char[] { '+', '-', '0', '.' });
            return value.Split(new char[] { '.' });
        }

        private static int Format16Char2Number(string c)
        {
            switch (c.ToUpper())
            {
                case "A":
                    return 10;
                case "B":
                    return 11;
                case "C":
                    return 12;
                case "D":
                    return 13;
                case "E":
                    return 14;
                case "F":
                    return 15;
                default:
                    return Convert.ToInt32(c);
            }
        }

        private static string Format16Number2Char(int number)
        {
            switch (number)
            {
                case 10:
                    return "A";
                case 11:
                    return "B";
                case 12:
                    return "C";
                case 13:
                    return "D";
                case 14:
                    return "E";
                case 15:
                    return "F";
                default:
                    return number.ToString();
            }
        }

        /// <summary>
        /// 其它进制转换为10进制(位乘法)
        /// </summary>
        /// <param name="value"></param>
        /// <param name="from"></param>
        /// <returns></returns>
        private static string OthersToTen(string[] values, int from)
        {
            string result = string.Empty;
            string integer = values[0];
            string temp = string.Empty;
            int integerCurrent = 0;
            int integerResult = 0;
            int index = integer.Length - 1;
            bool is16 = from == 16;
            foreach (var c in integer)
            {
                temp = c.ToString();
                integerCurrent = is16 ? Format16Char2Number(temp) : Convert.ToInt32(temp);
                integerResult += integerCurrent * (int)Math.Pow((double)from, (double)index);
                index--;
            }

            if (values.Length <= 1)
            {
                return integerResult.ToString();
            }
            else
            {
                string decimaler = values[1];
                double decimalerCurrent = 0.0;
                double decimalerResult = 0.0;
                index = -1;
                foreach (var c in decimaler)
                {
                    temp = c.ToString();
                    decimalerCurrent = is16 ? Format16Char2Number(temp) : Convert.ToDouble(temp);
                    decimalerResult += decimalerCurrent * Math.Pow((from), (double)index);
                    index--;
                }
                return (integerResult + decimalerResult).ToString();
            }
        }

        /// <summary>
        /// 10进制转换为其它进制(辗转相除法)
        /// </summary>
        /// <param name="values"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        private static string TenToOthers(string[] values, int to)
        {
            int integerCurrent = Convert.ToInt32(values[0]);
            int remainder = 1;
            bool is16 = to == 16;
            string integerResult = string.Empty;
            while (integerCurrent > 0)
            {
                remainder = integerCurrent % to;
                integerResult = (is16 ? Format16Number2Char(remainder) : remainder.ToString()) + integerResult;
                integerCurrent = integerCurrent / to;
            }
            if (values.Length <= 1)
            {
                return integerResult;
            }
            else
            {
                double decimalerCurrent = Convert.ToInt32(values[1]) / Math.Pow(10.0, (double)values[1].Length);
                int decimalerInt = 0;
                double decimalerDec = decimalerCurrent;
                string decimalerResult = string.Empty;
                string[] strArr;
                while (decimalerDec != 0)
                {
                    decimalerCurrent = decimalerDec * to;
                    //拆分double,得到整数和小数部分
                    strArr = decimalerCurrent.ToString().Split(new char[] { '.' });
                    decimalerInt = Convert.ToInt32(strArr[0]);
                    if (strArr.Length > 1)
                        decimalerDec = Convert.ToDouble(strArr[1]) / (Math.Pow(10.0, (double)strArr[1].Length));
                    else
                        decimalerDec = 0;
                    decimalerResult += is16 ? Format16Number2Char(decimalerInt) : decimalerInt.ToString();
                    //这里默认精确到32位,可以加个参数指定
                    if (decimalerResult.Length > 32)
                        break;
                }
                return integerResult + "." + decimalerResult;
            }
        }

        /// <summary>
        /// 其它进制互转。以10进制为中间值即可
        /// </summary>
        /// <param name="values"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        private static string OthersToOthers(string[] values, int from, int to)
        {
            string to10 = OthersToTen(values, from);
            values = to10.Split(new char[] { '.' });
            return TenToOthers(values, to);
        }
    }

顺带一句,【程序设计】,个人觉得最重要的是“设计”二字。在写代码前,我们需要理清逻辑,想好实现的过程;当设计好了,代码写起来会更快、bug 也会更少,测试起来也更容易。所以,碰到一个问题或需求,切记不要马上就敲代码。

文章评论

老程序员的下场
老程序员的下场
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员都该阅读的书
程序员都该阅读的书
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
鲜为人知的编程真相
鲜为人知的编程真相
每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
如何成为一名黑客
如何成为一名黑客
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员必看的十大电影
程序员必看的十大电影
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
那些争议最大的编程观点
那些争议最大的编程观点
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
我是如何打败拖延症的
我是如何打败拖延症的
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员的鄙视链
程序员的鄙视链
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
Java程序员必看电影
Java程序员必看电影
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
编程语言是女人
编程语言是女人
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
漫画:程序员的工作
漫画:程序员的工作
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
旅行,写作,编程
旅行,写作,编程
中美印日四国程序员比较
中美印日四国程序员比较
我的丈夫是个程序员
我的丈夫是个程序员
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员和编码员之间的区别
程序员和编码员之间的区别
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
为什么程序员都是夜猫子
为什么程序员都是夜猫子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员应该关注的一些事儿
程序员应该关注的一些事儿
总结2014中国互联网十大段子
总结2014中国互联网十大段子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有