2013-11-24 53 views
0

我有这个程序的小问题。我正在尝试创建一个C++程序来计算一个人的生活天数。它接受三个称为月,日和年的参数。这是该计划背后的整个逻辑:天计算器不总是产生准确的结果

  1. 首先计算今天的日期和保存到三个变量称为天,月,年,并寻找当年差

  2. 假设一年差为10,计算9年的天数乘以365.

  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

计算的日期是不是一个特别简单明了的任务,它更容易简单地使用验证算法,而不是尝试调试一个破碎的一个。

从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'; 
} 

之间的天数

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