Convert Seconds to Days, Hours, Minutes, and Seconds Using C++

  • Context: Comp Sci 
  • Thread starter Thread starter Bob Busby
  • Start date Start date
  • Tags Tags
    C++
Click For Summary

Discussion Overview

The discussion revolves around a programming homework problem that requires converting a user-input number of seconds into days, hours, minutes, and seconds using C++. Participants share their code attempts, identify issues, and suggest improvements related to data types and arithmetic operations.

Discussion Character

  • Homework-related
  • Technical explanation
  • Debate/contested

Main Points Raised

  • One participant expresses difficulty with their code, noting that the computed seconds value is consistently one less than expected.
  • Another participant suggests that using double for most variables may not be necessary, as long can hold the required integer values.
  • It is pointed out that truncating values during arithmetic operations can lead to discrepancies, particularly in the calculation of newSeconds.
  • Participants discuss the importance of integer division and the modulus operator in achieving correct results, with examples provided to illustrate these concepts.
  • One participant rewrites their code using only integer types and the modulus operator, claiming it works correctly, but asks for feedback on potential bugs.
  • There is a discussion about whether double types are needed for constants and variables, with some advocating for using long types exclusively.
  • Another participant explains that floating-point arithmetic can lead to precision issues, which may have contributed to the original problem encountered.

Areas of Agreement / Disagreement

Participants express differing views on the necessity of using double types versus long types for variables and constants. There is no consensus on the best approach, as some advocate for integer arithmetic while others suggest maintaining floating-point types for certain calculations.

Contextual Notes

Limitations include unresolved assumptions about the input values and the potential for precision loss in floating-point arithmetic. The discussion also highlights the varying interpretations of the problem and the solutions proposed by participants.

Bob Busby
Messages
44
Reaction score
0

Homework Statement


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.


Homework Equations





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()
{
count << "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);

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

return 0;
}
 
Physics news on Phys.org
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:
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.
 
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
 
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
 
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.
 
You can either use double for everything and round off the answer or (better) you can promote the arguments 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.
 
Bob Busby said:
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?

No, you didn't to use doubles, and moreover, you were pretty much told to use integers.
 
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()
{
count << "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;


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

return 0;
}
 
Bob Busby said:
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?
I would use long for all variables and constants, and the double type for neither.
Bob Busby said:
So the code should be:

newSeconds = (minutes * SECONDS_IN_MINUTE) - (int (minutes) - SECONDS_IN_MINUTE);
Here's a better way (all variables/constants are long) that doesn't use the % operator:
Code:
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
Bob Busby said:
Why did the way I did it work with in the other parts but not with seconds?
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.
Bob Busby said:
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.
 

Similar threads

  • · Replies 15 ·
Replies
15
Views
2K
Replies
4
Views
4K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 7 ·
Replies
7
Views
7K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 2 ·
Replies
2
Views
5K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K