天生计算器总是不能产生准确的结果

时间:2013-11-24 20:37:17

标签: c++ date calculator

我对这个程序有一个小问题。我正在尝试创建一个计算个人生活天数的c ++程序。它接受三个称为月,日和年的参数。这是该计划背后的全部逻辑:

  1. 首先计算今天的日期并保存为三个变量,分别称为日,月和年,并找出年份差异

  2. 假设年份差异为10,则乘以365计算9年中的天数。

  3. 假设输入月份为5,通过添加相应的天数计算4个月内的天数,并将结果值添加到总天数中。

  4. 计算从输入年到当年的闰年数,并将该值添加到总天数中。

  5. 函数返回最终输出但是我在某些日期会出现轻微错误。输出并不总是准确的。任何帮助将不胜感激。 下面是整个代码:

    #include <iostream>
    #include <ctime>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    bool IsLeap(int);
    int LeapCount(int);
    int current_year;
    int calculator(int month, int day, int year);
    
    int main()
    {
       cout << calculator(9,24,1994);
    }
    
    int calculator(int month, int day, int year)
    {
        int final_result;
        int day_difference;
        int total_days = 0;
        const int days_inayear = 365;
        vector <int> m_days = {31,28,31,30,31,30,31,31,30,31,30,31};
    
        time_t theTime = time(NULL);
        struct tm *aTime = localtime(&theTime);
    
        int current_day = aTime->tm_mday;
        int current_month = aTime->tm_mon + 1;
        current_year = aTime->tm_year + 1900;
    
        if(year > current_year){
            return 0;
        }
        else if (year == current_year && month > current_month){
            return 0;
        }
        else if(year == current_year && month == current_month && day > current_day){
            return 0;
        }
        else if(year == current_year &&month == current_month && day <= current_day){
                return abs(current_day - day);
        }else
        {
            int year_difference = current_year - year;
            int day_difference = abs(current_day - day);
           for(int a = month+1; a < m_days.size(); a++){
                total_days+= m_days[a];
           }
        int leap_years = LeapCount(year);
    
         total_days+=(year_difference)*days_inayear;
        if(year_difference <= 1 && month < 2){
            leap_years -= 2;
        }
    
        final_result = total_days+leap_years+day_difference;
        if(IsLeap(year) && month > 2){
            final_result = final_result;
        }
        return final_result;
    }
    }
    bool IsLeap(int year)
    {
        if(year%4 == 0 && year%100!=0){
            return true;
        }
        else if(year%4==0 && year%100==0 && year%400==0){
            return true;
        }
        else{
            return false;
        }
    }
    int LeapCount(int year)
    {
       int difference = current_year - year;
       int count = 0;
       for(int x = 0; x<=difference; x++){
            if(IsLeap(year+x)){
                count++;
            }
       }
       return count;
    }
    

1 个答案:

答案 0 :(得分:0)

使用日期计算并不是一项特别简单明了的任务,只是简单地使用经过验证的算法而不是尝试调试破坏的算法更容易。

来自Howard Hinnant的论文chrono-Compatible Low-Level Date Algorithms,这是一个算法,计算自1970-01-01以来的天数:

#include <limits>
#include <iostream>

// Returns number of days since civil 1970-01-01.  Negative values indicate
//    days prior to 1970-01-01.
// Preconditions:  y-m-d represents a date in the civil (Gregorian) calendar
//                 m is in [1, 12]
//                 d is in [1, last_day_of_month(y, m)]
//                 y is "approximately" in
//                   [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
//                 Exact range of validity is:
//                 [civil_from_days(numeric_limits<Int>::min()),
//                  civil_from_days(numeric_limits<Int>::max()-719468)]
template <class Int>
constexpr
Int
days_from_civil(Int y, unsigned m, unsigned d) noexcept
{
    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<Int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    y -= m <= 2;
    const Int era = (y >= 0 ? y : y-399) / 400;
    const unsigned yoe = static_cast<unsigned>(y - era * 400);      // [0, 399]
    const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1;  // [0, 365]
    const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy;         // [0, 146096]
    return era * 146097 + static_cast<Int>(doe) - 719468;
}

这个实现碰巧使用C ++ 14的功能,但是将其转换为C ++ 11甚至是C ++ 98并不困难。

这是一个非常聪明的算法。霍华德的论文详细解释了这些细节。

要计算两个日期之间的天数,请使用此算法计算两个不同日期的纪元的天数,然后减去这些值以获得它们之间的天数

int main() {
    int serial_birth_date = days_from_civil(1994, 9, 24);
    int serial_current_date = days_from_civil(2013, 11, 24);
    std::cout << "Days lived: " << serial_current_date - serial_birth_date << '\n';
}

如果您真的想调试自己的算法,可以使用霍华德发布的算法作为基线。将程序的各个组件的结果与使用这些算法计算的结果进行比较,以将问题缩小到单个组件。比较大量测试用例的结果,也许你会在错误中看到一个模式。