# Homework Help: Beginner's C++ question

1. Jun 25, 2010

### Bob Busby

1. The problem statement, all variables and given/known data
Write a program that asks the user to enter the number of seconds as an integer value
(use type long) and that then displays the equivalent time in days, hours, minutes, and
seconds. Use symbolic constants to represent the number of hours in the day, the number of minutes in an hour, and the number of seconds in a minute. The output should
look like this:

Enter the number of seconds: 31600000
31600000 seconds = 365 days, 46 minutes, 40 seconds

I'm a newcomer to programming and c++ and I'm having a bit of trouble with this problem. Everything works beautifully until the computation for newSeconds near the bottom of the code. No matter what value I feed it for "seconds," "secondsFinal" is always 1 less than "newSeconds." I have no idea what is going on. Any help would be appreciated.

2. Relevant equations

3. The attempt at a solution

#include <iostream>

const double SECONDS_IN_MINUTE = 60;
const double MINUTES_IN_HOUR = 60;
const double HOURS_IN_DAY = 24;

using namespace std;

int main()
{
cout << "Enter a number of seconds: ______\b\b\b\b\b\b";
long seconds;
cin >> seconds;
double days, hours, minutes, newSeconds; //for computation
int daysFinal, hoursFinal, minutesFinal, secondsFinal; //for display
days = seconds / SECONDS_IN_MINUTE / MINUTES_IN_HOUR / HOURS_IN_DAY; //converts seconds to days
daysFinal = int (days); //gets the integer part of days

hours = (days - int (days)) * HOURS_IN_DAY; //gets the noninteger part of days even if days is < or > an integer
hoursFinal = int (hours);

minutes = (hours - int (hours)) * MINUTES_IN_HOUR;
minutesFinal = int (minutes);

newSeconds = (minutes - int (minutes)) * SECONDS_IN_MINUTE;
secondsFinal = int (newSeconds);

cout << seconds << " seconds = " << daysFinal << " days, " << hoursFinal << " hours, " << minutesFinal << " minutes, " << secondsFinal << " seconds.";

return 0;
}

2. Jun 25, 2010

### Staff: Mentor

Why are you using double for most of your variables? The long type is capable of holding integers up through 2,147,483,647.

The reason for your discrepancy is this line of code:
Code (Text):
newSeconds = (minutes - int (minutes)) * SECONDS_IN_MINUTE;
You are truncating minutes and then multiplying by SECONDS_IN_MINUTE. A better way would be to multiply first by this constant and then truncate the fractional part.

3. Jun 26, 2010

### mgb_phys

Just to reinforce Mark's point, C and C++ don't promote integer arithmatic if the answer is integer.

so (int)2/(int)3 = 0

4. Jun 26, 2010

### Staff: Mentor

You really should be thinking in terms of integer division and the modulus operator here. For example, let's make a simpler problem for the purposes of discussion, and suppose you want to convert 358 seconds into minutes and seconds.

358 / 60 == 5
358 % 60 == 58

Note that there are two kinds of division in C/C++: integer division and floating point division. If both operands of a division expression are integer types (short, int, long), the result will be an integer value. If at least one of the operands is a floating point type, the result will be a floating point value.

I.e., 3/2 == 1
but 3.0/2 == 1.5

5. Jun 26, 2010

### Bob Busby

I see that I didn't need to use the double type for my constants but I did need it for all the other variables I used it on, right?

So the code should be:

newSeconds = (minutes * SECONDS_IN_MINUTE) - (int (minutes) - SECONDS_IN_MINUTE);

Why did the way I did it work with in the other parts but not with seconds?

By the way I figured using the modulus operator would be the better way to go, but the book hadn't mentioned it yet at this point so I was trying to solve the problem an alternate way.

6. Jun 26, 2010

### mgb_phys

You can either use double for everything and round off the answer or (better) you can promote the arguements in the function.

newSeconds = (minutes * (double)SECONDS_IN_MINUTE) - (int (minutes) - SECONDS_IN_MINUTE);

(double)SECONDS_IN_MINUTE is a slightly odd c way of saying treat the SECONDS_IN_MINUTE as a double for this statement.
you can also do the int (minutes) in the same way, int (minutes) is identical to (int)minutes

There is also a ceil() and floor() function that rounds up/down a double which you migth not have seen yet.

7. Jun 26, 2010

### D H

Staff Emeritus
No, you didn't to use doubles, and moreover, you were pretty much told to use integers.

8. Jun 26, 2010

### Bob Busby

If I hadn't used double then this and all similar parts of the code wouldn't work.

hours = (days - int (days)) * HOURS_IN_DAY;

I don't care if I'm not following the book's instructions to a T. I'm trying to make the code work with the method I envisioned. So any help with my question in the last post would still be appreciated.

Anyway, I rewrote the code using only type int and the modulus operator. It seems to work perfectly, but tell me if it has any unobvious bugs.

const int SECONDS_IN_MINUTE = 60;
const int MINUTES_IN_HOUR = 60;
const int HOURS_IN_DAY = 24;

using namespace std;

int main()
{
cout << "Enter a number of seconds: ";
long seconds, minutes, hours, days; //for computation
int secondsFinal, minutesFinal, hoursFinal, daysFinal; //for display
cin >> seconds;

secondsFinal = seconds % SECONDS_IN_MINUTE;
minutes = seconds / SECONDS_IN_MINUTE;

minutesFinal = minutes % MINUTES_IN_HOUR;
hours = minutes / MINUTES_IN_HOUR;

hoursFinal = hours % HOURS_IN_DAY;
days = hours / HOURS_IN_DAY;

cout << seconds << " seconds = " << days << " days, " << hoursFinal << " hours, " << minutesFinal << " minutes, and " << secondsFinal << " seconds.";

return 0;
}

9. Jun 26, 2010

### Staff: Mentor

I would use long for all variables and constants, and the double type for neither.
Here's a better way (all variables/constants are long) that doesn't use the % operator:
Code (Text):

newSeconds = seconds - seconds/SECONDS_IN_MINUTE * SECONDS_IN_MINUTE;

Assuming that seconds is 358, the code above evaluates 358 - 358/60 * 60 and stores it in newSeconds. This expression is evaluated like this.
358 - 358/60 * 60
= 358 - 5 * 60
= 358 - 300
= 58
The short answer is that floating point arithmetic is not exact while integer arithmetic is exact. Floating point numbers are stored in memory in 32 or 64 bits. As a result, precision is sometimes lost, in the same way as when you use .333 to represent 1/3. 3 * .333 = .999 while 3 * (1/3) = 1.0.
Surprisingly, some numbers that have finite-length decimal representations, such as 0.1, have machine representations that are different from their decimal representations. This causes problems such as the one you experienced with an incorrect value for newSeconds.