3

I am trying to learn basic C programming by following a textbook and I must be missing something about either the data types, rounding, and/or order of operations because when I try to construct a simple program to convert seconds to hours and minutes, the hours work but the remaining minutes come out to 0 when they should not be.

Thanks to Coursera, I am aware that there are huge security vulnerabilities with programs like this, but for learning purposes I'll ask you to ignore security. For now, the books wants me to stick to using printf, scanf, and a while loop as they correspond to the chapters of the textbook I'm reading (the books lets me know that I'll get to start worrying about security when I'm a few chapters further along).

My C program looks like this:

/* Ask the user for a number of seconds, convert to X hours and Y minutes */
/* Continue doing this with a while loop until user enters 0 */
#include <stdio.h>
#include <conio.h>
#include <string.h>

int main(void)
{
    const int minperhour = 60;
    const int secpermin  = 60;
    int sec, hr;
    float min;
    sec = 1;
    while(sec != 0)
    {
        printf("Enter the number of seconds to convert: \n");
        scanf("%i", &sec);
        min = sec/secpermin;
        hr  = min/minperhour;
        min = (sec/secpermin) - (hr * minperhour);
        printf("%d hours and %f minutes \n", hr, min);
    }

    return 0;
}

I would expect that I could enter 3601 and the result would be:

1 hours and 0.01667 minutes

because this is how the expression is evaluated in the R language, with which I'm more familiar:

> min = 3601/60
> min
[1] 60.02
> hr = min/60
> hr
[1] 1
> min = (3601/60) - (1 * 60)
> min
[1] 0.01667

However, what I get in C is this:

C:\Users\hackr>pa2q3.exe
Enter the number of seconds to convert:
3601
1 hours and 0.000000 minutes
Enter the number of seconds to convert:
7205
2 hours and 0.000000 minutes
Enter the number of seconds to convert:
0
0 hours and 0.000000 minutes

C:\Users\hackr>

I threw in the 7205 second attempt just for good measure.

I have a feeling that some of the you C gurus on Stack Overflow could use more advanced techniques to write a secure version of the program in some more succinct form. This may be educational as well if you want to mention it, but first and foremost I need to understand what's going on with this simple program.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
Hack-R
  • 22,422
  • 14
  • 75
  • 131
  • 3
    http://stackoverflow.com/questions/3602827/what-is-the-behavior-of-integer-division-in-c – Kik May 06 '15 at 14:39
  • Does this answer your question? [Division result is always zero](https://stackoverflow.com/questions/2345902/division-result-is-always-zero) – phuclv Aug 23 '20 at 04:43

1 Answers1

5

Integer division: the integer value after dividing two ints gets stored in a floating point format. Eg:

 float a = 3/5;

here an integer division will occur between 3 and 5 resulting in 0. Now, if you try to store this 0 in a float variable, it will be stored as 0.00.

    min = sec/secpermin;

Should be

    min = (float)sec/secpermin;

or

    min = sec/(float)secpermin;

or, as @alk pointed out, you could also do this instead:

    min = sec;     
    min /= secpermin;    // min=min/secpermin;   here, typecasting is not required as 
                        // numerator (min) is already float.

Alternatively, you can make them all float, and while printing typecast them as int.

Ayushi Jha
  • 4,003
  • 3
  • 26
  • 43
  • Thank you very much. I wonder if I missed this in the book or if this is new information. I will have to double check. Either way this is very helpful and I will accept it as the solution, thanks! – Hack-R May 06 '15 at 14:40
  • 3
    Clearer explanation: The result of an integer division is an integer in `C` the fractional part is thrown away. The cast to float of one of the integers turns it into a float division which works as expected – DrKoch May 06 '15 at 14:42
  • 2
    Although the O.P. intends to do float division, you should at least warn him that this approach is subject to severe rounding error - and tell about the remainder operator. Could you? – jsbueno May 06 '15 at 14:42
  • Yeah, I was adding all that now. – Ayushi Jha May 06 '15 at 14:43
  • 1
    Or without casting: `min = sec; min /= secpermin;` – alk May 06 '15 at 14:46
  • 1
    Also there is no need to cast when assigning `hr` as `min` is already typed `float`. Short: `min/minperhour;` isn't an integer division. – alk May 06 '15 at 14:48
  • Those code snippets are misleadingly giving the impression the assignement to `hr` needs to be casted to `float` to avoid integer divsion, which is not the case. 1- for this. Please correct this. – alk May 06 '15 at 14:54