代码优化如做游戏一样有趣

来源:互联网 发布:淘宝上买号怎么领取 编辑:程序博客网 时间:2024/04/30 16:30

认认真真地写好一段代码,写好一个函数,也是很有乐趣的一件事情。


1. 比如说对于这样一个小题目:

在一50人的队列中,从左至右报数,为单数者出列,其他人再从左至右报数,为单数者出列,直至剩下最后一人,问此人是初始队列中的第多少号?

意看到这个描述,那么当然有一种顺理成章的做法,如下所示:

namespace Exam01{    using System.Collections.Generic;    /// <summary>    /// TODO: Update summary.    /// </summary>    public class Utility    {        private List<int> numbers = new List<int>();        public Utility()        {            for (int i = 1; i <= 50; i++)            {                numbers.Add(i);            }        }        public int Run()        {            while (numbers.Count > 1)            {                int start =                    ((numbers.Count >> 1) << 1) == numbers.Count ?                    numbers.Count - 1 :                    numbers.Count;                for (int i = start - 1; i >= 0; i -= 2)                {                    numbers.RemoveAt(i);                }            }            return numbers[0];        }    }}

这个做法显然不是最优的。

经过简单的分析,我们可以看到,每一轮去除单数元素后,每次得到的新的数列中,第一个元素的值是很有规律的。这个规律就是2的n次方,n从0开始取值。

所以上面的Run()函数我们优化为下面这样的:

        public int Run()        {            int start = 1;            int k = 50 >> 1;            while (start <= k)            {                start <<= 1;            }            return start;        }

再举两个代码优化的小例子:

2. 如何把月份转换成季度

先看一下某论坛帖子里面的代码:

public int ConvertMonthToQuarter(int month){     double f = Convert.ToDouble(month)/3f;    if (f > Convert.ToInt32(f))    {        return Convert.ToInt32(f) + 1;    }    return Convert.ToInt32(f);}

这段代码当然质量是惨不忍睹的。下面是我的优化:

/// <summary>/// Get quarter of the year by month value./// Notice: valid month range is [1 -- 12]/// </summary>/// <param name="month">month value.</param>/// <returns>quarter value of the year</returns>public int GetQuarterByMonth(int month){    if (month < 1 || month > 12)    {        string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);        throw new ArgumentOutOfRangeException("month", message);    }    int q = month / 3;    return q * 3 < month ? q + 1 : q;}

然后,略微一思考,进一步优化如下:

/// <summary>/// Get quarter of the year by month value./// Notice: valid month range is [1 -- 12]/// </summary>/// <param name="month">month value.</param>/// <returns>quarter value of the year</returns>public int GetQuarterByMonth(int month){    if (month < 1 || month > 12)    {        string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);        throw new ArgumentOutOfRangeException("month", message);    }    return (month - 1) / 3 + 1;}

现在这个函数看起来终于像样了吧。


3. 获得本月份是本季度的第几个月

先看一下某论坛帖子里面的代码:

public int GetMonthOfQuarter(int month){    int num = month % 3;    if (num == 0)    {        return 3;    }    return num;}

我对其优化如下:

/// <summary>/// Get month sequence of the quarter./// Notice: valid month range is [1 -- 12]/// </summary>/// <param name="month">month value.</param>/// <returns>month sequence of the quarter</returns>public int GetMonthSeqOfQuarter(int month){    if (month < 1 || month > 12)    {        string message = string.Format("Input parameter month ({0}) out of range[1 -- 12].", month);        throw new ArgumentOutOfRangeException("month", message);    }    int k = (month - 1) / 3;    return month - 3 * k;}


雕虫小技耳。但是也挺有意思。微笑