1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Homework Help: Beginner's C++ question

  1. Jun 25, 2010 #1
    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. jcsd
  3. Jun 25, 2010 #2

    Mark44

    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.
     
  4. Jun 26, 2010 #3

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    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
     
  5. Jun 26, 2010 #4

    Mark44

    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
     
  6. Jun 26, 2010 #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.
     
  7. Jun 26, 2010 #6

    mgb_phys

    User Avatar
    Science Advisor
    Homework Helper

    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.
     
  8. Jun 26, 2010 #7

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    No, you didn't to use doubles, and moreover, you were pretty much told to use integers.
     
  9. Jun 26, 2010 #8
    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;
    }
     
  10. Jun 26, 2010 #9

    Mark44

    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.
     
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook