Thread: Short program overflow issue?

  1. #1
    Registered User
    Join Date
    Feb 2008
    Location
    Yokohama
    Posts
    48

    Short program overflow issue?

    There is a question in my text C Primer + that wants you to convert your age into seconds and it tells you that there are 3.156x(10 to the power of seven) seconds in a year. So I came up with the following program which produces the same output for every age. From that I a can see that I messed up. Can anyone see where I went wrong? My guess is that a long double isn't big enough to hold that no. of seconds.

    Code:
    /* convert age from years to seconds */
    #include <stdio.h>
    int main(void)
    {
    	int age;
    	long double seconds_age;
    
    	seconds_age = age * 3.156e7;
    	printf("Enter your age: ");
    	scanf("%d", &age);
    
    	printf("%d years is %lf seconds", age, seconds_age);
    }

  2. #2
    Registered User NeonBlack's Avatar
    Join Date
    Nov 2007
    Posts
    431
    Code:
    seconds_age = age * 3.156e7;
    This is not an equation. It takes the current value of age times 3.156e7 and puts it into seconds_age. In other words, you need to know age BEFORE you make this assignment.
    I copied it from the last program in which I passed a parameter, which would have been pre-1989 I guess. - esbo

  3. #3
    Registered User
    Join Date
    Feb 2008
    Location
    Yokohama
    Posts
    48
    Now, that I have posted I think I know my mistake. The statement order was wrong. I should have put the seconds_age = age * 3.156e7; after the scanf. Because I didn't the printf is reading seconds_age as an undeclared variable and producing garbage. I am just guessing though.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Location
    Yokohama
    Posts
    48
    Quote Originally Posted by NeonBlack View Post
    In other words, you need to know age BEFORE you make this assignment.
    Thanks. Just figured that out while you were posting. It makes sense of course.

  5. #5
    Registered User
    Join Date
    May 2008
    Posts
    53
    You are quite optimistic as to how old you're going to get.

    The float data type is guaranteed to be able to hold at least 3.40282347E+38, which corresponds to about 10^30 years.
    Are you sure you need a long double? :-)

    --
    Computer Programming: An Introduction for the Scientifically Inclined

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    God might use the program

    Incidentally, 3.156e7 is a double literal. 3.156e7L (or 3.156e7l) is the corresponding long double literal.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    You don't, in fact, need a double at all. An int should be big enough, otherwise use a long. You should avoid using floats and doubles wherever possible. Computers cannot accurately represent decimal places (especially, repeating patterns like 1/3), so they are approximated. This can sometimes lead to problems where you store 1.0 in a float, but it gets printed as .999999999999

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  8. #8
    Registered User
    Join Date
    Feb 2008
    Location
    Yokohama
    Posts
    48
    Thanks for the feedback. I do hope to live for a long time but I agree. It's probably longer than I need.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You don't, in fact, need a double at all. An int should be big enough, otherwise use a long.
    A long may not be long enough, since long is only guaranteed an upper bound of 2147483647, and many people live for more seconds than that. An unsigned long, on the other hand, would cut it, at least for now (though I have read of unsubstantiated claims of people living as long as 150 years).

    You should avoid using floats and doubles wherever possible.
    I agree.

    Computers cannot accurately represent decimal places (especially, repeating patterns like 1/3), so they are approximated. This can sometimes lead to problems where you store 1.0 in a float, but it gets printed as .999999999999
    That said, I believe 1.0 can be accurately and precisely represented in most, if not all, floating point representations, including IEEE 754.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by QuantumPete View Post
    Computers cannot accurately represent decimal places (especially, repeating patterns like 1/3), so they are approximated.
    Really? I find that hard to believe.
    No, I suspect it's the way it is to gain reasonable range for floats and doubles while still maintaining a relatively low space requirement for the variables.
    More likely, it's the IEE standard which makes it difficult to represent non-approximated numbers.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    May 2008
    Posts
    53
    Quote Originally Posted by QuantumPete View Post
    You don't, in fact, need a double at all. An int should be big enough, otherwise use a long. You should avoid using floats and doubles wherever possible. Computers cannot accurately represent decimal places (especially, repeating patterns like 1/3), so they are approximated. This can sometimes lead to problems where you store 1.0 in a float, but it gets printed as .999999999999
    This story is often told to children to scare them away from floats, but it's really not so bad. If you do

    Code:
    float f = 1.0;
    then f will contain exactly 1, and you can safely cast it to integer. However, if you do

    Code:
    float f = 1.0;
    f = f/3;
    f = f*3;
    (assuming a compiler won't be bold enough so as to optimize away this code) then f will indeed be slightly below 1, and casting it to an integer will yield zero.

    As long as the value you store in a float will "fit" within the mantissa (i.e. the decimal point doesn't float :-) ) it will still be exact.

    --
    Computer Programming: An Introduction for the Scientifically Inclined

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Really? I find that hard to believe.
    No, I suspect it's the way it is to gain reasonable range for floats and doubles while still maintaining a relatively low space requirement for the variables.
    More likely, it's the IEE standard which makes it difficult to represent non-approximated numbers.
    No, QuantumPete is correct on that point. Take the example of 1/3. If you attempt to precisely express that in decimal, you will find that you eventually get bored of writing 3s, as in 0.333333333333... Likewise, precisely expressing 1/3 in binary has the same problem. You could, however, precisely express 1/3 in base 3, namely as 10, but then you would have problems precisely expressing other numbers in base 3.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    1/3 is an obvious problematic number, but floats have additional approximation problems due to that they're basically base raised to an exponent IIRC.
    They could use 8 bytes for base and 8 bytes for floating part and you would be able to represent a lot of numbers with exact precision. But it might be a waste of space...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Actually, floating point numbers consist of a sign, a mantissa (not "base", but number betwee 0.0 and 1.0 expressed in base 2), and an exponent. The actual number is then sign * mantissa * 2 ^ exponent.

    Since the mantissa has a limited number of bits (for example 24 or 53 for float and double in IEEE-754), there is a limit to how precisely we can describe numbers that are infinitely repeating when expressed in base 2. 1/3 in base 3, as explained, is a precise value of 0.1(3), just like 1/2 in base 2 is 0.1. Decimal [base 10] 0.1 can not be described precisely in binary, nor can any other number that is a even power of 2 multiple of 0.1 (e.g. 0.2, 0.4, 0.8, 1.6). If the number is a power of 2 + (0.1 * power of 2), then it's also going to be an endless sequence.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Quote Originally Posted by laserlight View Post
    You could, however, precisely express 1/3 in base 3, namely as 10, but then you would have problems precisely expressing other numbers in base 3.
    10 in base 3 is 3, not 1/3, right?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Issue with program that's calling a function and has a loop
    By tigerfansince84 in forum C++ Programming
    Replies: 9
    Last Post: 11-12-2008, 01:38 PM
  2. Help calling function is asm
    By brietje698 in forum C++ Programming
    Replies: 24
    Last Post: 12-06-2007, 04:48 PM
  3. short int vs int
    By time789 in forum C Programming
    Replies: 3
    Last Post: 08-05-2007, 09:37 AM
  4. Say what? - Weird error.
    By Blackroot in forum C++ Programming
    Replies: 6
    Last Post: 08-15-2006, 11:54 PM
  5. Replies: 2
    Last Post: 05-10-2002, 04:16 PM