-4

For a school project I need to calculate the leap years. The problem is, I need to round the int.

For example someone is born in 1961.

double yearsbetween; yearsbetween = birthyear - 1918;

double leapyears; leapyears = ( yearsbetween / 4 );

If birthyear = 1961 I get leapyears = 10.75 but that is wrong.. I need to be 11.

If an answer is 10.25 it need to be rounded to 10. If an answer is 10.75 it need to be rounded to 11.

Can someone help me ?

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
nvr
  • 9
  • 1
  • 1
    Can you show how you are calculating the leap years? You shouldn't need to round at all. – NathanOliver Sep 18 '18 at 16:47
  • Why would you use floating point numbers when dealing with integer values such as years? –  Sep 18 '18 at 16:47
  • 2
    11/4 is actually 2.75, not 10.75. I think you meant (1961-1918)/4=10.75. Programming requires you to be precise, just like math ! – MSalters Sep 18 '18 at 16:49
  • I don't think you can use an arithmetic formula to determine the number of leap years. I think you will need to iterate from the first year to the last and count leap years. – Tim Randall Sep 18 '18 at 16:50
  • 1
    `std::ceil` will do it for you. –  Sep 18 '18 at 16:51
  • Sure. For example someone is born in 1961. The year I calculate is from is 1918. So I do 1961-1918. Then I get 43 years. Then I do 43/4 and I get 10 (if I use double I get 10.75). But the real answer is 11 leapyears .. and not 10. – nvr Sep 18 '18 at 16:51
  • @HelloWorld: Perhaps. But Nien hasn't posted any code, so we can't tell. – MSalters Sep 18 '18 at 16:51
  • You are probably doing integer math somewhere in your calculation. – drescherjm Sep 18 '18 at 16:52
  • @MSalters sure. –  Sep 18 '18 at 16:52
  • Where is the OP? –  Sep 18 '18 at 16:56
  • I added some. I hope you understand now. I'm all new to this, sorry if its not clear for you. – nvr Sep 18 '18 at 16:58
  • Include something (code) you tried so far, so that someone will help you. –  Sep 18 '18 at 17:00
  • C# code but should work for you (no rounding required): https://stackoverflow.com/a/4587611/4342498 – NathanOliver Sep 18 '18 at 17:01
  • "How to round numbers" - [std::round](https://en.cppreference.com/w/cpp/numeric/math/round) and friends are a good start. See also [std::floor](https://en.cppreference.com/w/cpp/numeric/math/floor) and [std::ceil](https://en.cppreference.com/w/cpp/numeric/math/ceil). – Jesper Juhl Sep 18 '18 at 17:10
  • A small nit... When you have a range like `[a, b]`, the number of elements in the range is `b - a + 1` (not `b - a`). You can easily verify it with `[0,3]`, which has elements `{0,1,2,3}`. It may explain why you are off. You calculation may be off by one here: `birthyear - 1918`, which results in being off by `0.25` here: `leapyears = ( yearsbetween / 4 );`. You should probably ask your teacher for more test cases to cover edge cases, like a centurion/100 year old person born in 1900 and dies in 1999, 2000 or 2001. – jww Sep 19 '18 at 00:32

4 Answers4

2

you have to specifically look at each year to check for leap years. your assumption of every 4th year as leap is wrong, as there are some exceptions:

it is not a leap year, if it is divisible by 100 and not divisible by 400

examples:

  • 1900 is not a leap year
  • 2000 is a leap year

see https://en.wikipedia.org/wiki/Leap_year#Algorithm

skeller
  • 1,151
  • 6
  • 6
1

Suppose we are working only in a period in which the leap years are those years, and only those years, that are divisible by four.

Given a number n, the number of positive numbers less than or equal to n that are multiples of four is floor(n/4). Let L(n) be this value, floor(n/4).

If we take a number m, the number of positive multiples of four up to m is L(m). When we subtract L(n), the result, L(m)−L(n), is the number of multiples of four greater than n but less than or equal to m.

Therefore, the number of leap years between year 1918 and year m is floor(m/4) − floor(1918/4) = floor(m/4) − 479. (If the base year were a leap year and we wanted to include it inside the period instead of outside, we could replace L(n) with L(n−1).

The above is easily extendable to the larger leap year pattern. By changing L(n) to floor(n/4) − floor(n/100) + floor(n/400), it becomes a count of positive numbers up to n that are multiples of four but are not multiples of 100 unless they are multiples of 400. Then L(m) − L(n) is the number of leap rules between n and m.

Thus a proper formula for the period covered by this rule is floor(n/4) − floor(n/100) + floor(n/400) − 464. Using C’s integer arithmetic, this is easily evaluated as n/4 - n/100 + n/400 - 464.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Seems like what you need is std::ceil

You also have in the std::ceil reference a link to other rounding functions, I recommend going through those also.

dana
  • 11
  • 2
  • 2
    While this answers the literal question it doesn't point out that the OP's formula is flawed and will add extra leap years for certain date ranges. – NathanOliver Sep 18 '18 at 17:02
  • That is true, I did only answer the literal question. My bad there. – dana Sep 18 '18 at 17:31
0

So this isn't relevant until and I even had to ask a question to figure out how to use chrono::year. But the best solution for this, if available, would be something like:

const chrono::year birthyear{ 1961 };
auto leapyears = 0;

for(chrono::year i{ 1918 }; i <= birthyear; ++i) {
    if(i.is_leap()) {
        ++leapyears;
    }
}

I've linked a live example by forking @HowardHinnant's example from this answer.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288