实现功能的更好方法

时间:2015-07-06 08:17:23

标签: c++

假设指定的日期有效且属于公历,我们假设爱丽丝和鲍勃被分配了一个函数,为格里高利历的给定日期返回星期几。

是否有广泛接受的指南(或最佳做法),允许告诉哪些代码更好,为什么?

爱丽丝:

int getDayOfWeek(int day, int month, int year)
{
    int monthBias[] = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
    int yearsBefore = year - 1;

    unsigned int result = yearsBefore + yearsBefore / 4 - yearsBefore / 100 + yearsBefore / 400 + monthBias[month - 1] + day;

    if (year % 4 == 0 && month > 2 && (year % 100 != 0 || year % 400 == 0))
        ++result;

    return result % 7;
}

鲍勃:

enum DayOfWeek
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,

    count
};

inline int getLeapYearsBefore(int year)
{
    int yearsBefore = year - 1;

    return yearsBefore / 4 - yearsBefore / 100 + yearsBefore / 400;
}

inline bool isLeapYear(int year)
{
    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}

using namespace std;

template <typename T, size_t n>
constexpr size_t arraySize(T (&)[n]) { return n; }

DayOfWeek getDayOfWeek(int day, int month, int year)
{
    const int
        commonYear[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
        leapYear[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },

        daysInCommonYear = accumulate(commonYear, commonYear + arraySize(commonYear), 0),
        daysInLeapYear = accumulate(leapYear, leapYear + arraySize(leapYear), 0),

        yearsBefore = year - 1,
        leapYearsBefore = getLeapYearsBefore(year),
        commonYearsBefore = yearsBefore - leapYearsBefore;

    auto kindOfYear = isLeapYear(year) ? leapYear : commonYear;

    unsigned int result =
        (leapYearsBefore * daysInLeapYear
        + commonYearsBefore * daysInCommonYear
        + accumulate(kindOfYear, kindOfYear + month - 1, day)) % DayOfWeek::count;

    return static_cast<DayOfWeek>(result);
}

性能比较并没有为Alice的代码带来可检测的优势,因为我试图测量Alice和Bob的实现的性能差异,但是失败了(使用high_resolution_clock::now()duration_cast<nanoseconds>(end - start)) - 至少我可以说差异小于0.5%(在500万次通话中平均通话时间之间)。

3 个答案:

答案 0 :(得分:2)

如果您正在寻找指导方针,我建议您阅读Stroustrup的C ++编程语言书。

但简单地说,这是两种不同的方法:

Alice方法(为什么要使用它): 用于需要高性能的程序的简单方法 - 一个功能(一个电话) - 仅在需要时声明变量 - 使用已知大小的静态分配向量 - 没有详尽使用对象副本。

Bob方法(为什么应该使用它):

它基于分而治之的策略。 - 每个函数负责一个任务(如果您希望将来维护代码,则非常有用) - 用于其他目的的高度可重用代码。

答案 1 :(得分:1)

与生活中一样,没有比较两种方法的简单方法,不同的人可能对他们有不同的看法。如果要将这些功能合并到生产代码中,那么有两件事情会计算在内:

  1. 理解,验证和维护代码有多容易。在这方面,鲍勃的方法显然获胜。在爱丽丝的代码中,有两个“隐秘的”#34;数字不够明显。至少有一些评论有助于了解她是如何达成解决方案的。
  2. 代码的执行速度有多快。如果这是一个被称为数百万次的通用库例程,那就是可以计算的。仅仅从查看代码,我猜想Alice的方法稍快一点。但这只是一个假设,需要在理想的平台上进行衡量。
  3. 所以&#34;清除&#34;答案是:取决于

    假设鲍勃的代码只是稍微慢了一点,而且这个功能并不是那么重要,那么我会投票选择鲍勃的方法 - 做完一些时间后。

答案 2 :(得分:-1)

它们与@ tobi303说的不同,但我看到第一个实现的计算量较少,第二个更容易理解。

如果它们相似,你可以按照提到的测试用例和性能测量(即执行时间)进行比较。

修改:&#34;我看到&#34;第二个是可以理解的,因为有意义的标识符。

year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)

如果我没有读取函数名,我不知道得到真实结果意味着什么。