Shotgecko
Shotgecko

Reputation: 35

Printf comes out negative

I'm new to programming and am trying to have my program take a given number, double it, then continue to double for however many days the user input. I made this loop and it works but the final number comes out negative. I'm not sure how I can stop it from coming out negative and would appreciate any help.

int main(void)
{

    int d;
    int s;
    float a;

    do
    {
        printf ("Please enter the amount of days in the month: ");
        d = GetInt();   
    } while (d > 31 || d < 28);

    do 
    { 
        printf("Please enter the amount of pennies you start will start with: ");
        s = GetInt();
    } while( s < 0);

    do 
    {    
        s = s * 2;
        d = d - 1;
        a = s / 100.0;
        printf("%f\n", a);

    } while(d > 0);

    return 0;
}

Upvotes: 3

Views: 1714

Answers (3)

autistic
autistic

Reputation: 15652

Section 6.5p5 of the C standard:

If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.

What this says is that any int expression that is greater than INT_MAX, or less than INT_MIN will cause problems. Those problems aren't defined, so you can't handle them; It's best to avoid things like that. In your case, the calculation wraps into negative values as explained above. That isn't required, however. Perhaps if you were to compile and run this on a different system, with a different compiler, your program may crash, or it may seem to work as expected, somehow representing an infinite set of values in a finite storage space, or a chicken may run around headless for a few minutes... Who knows?

You can avoid this problem by carefully choosing a type that has a wider range, as is covered in the other answers, and enforcing a ceiling value on your inputs so that no overflow is possible. Another method would be to use an arbitrary precision arithmetic library such as GNU MP Bignum which shouldn't overflow.

Upvotes: 1

jim mcnamara
jim mcnamara

Reputation: 16399

2^31 = 2147483648

If there are more than 30 days you will overflow an integer even starting with 1 penny and doubling the value. If you start with a larger number of pennies you overflow sooner.

When an integer overflows, it displays as a negative value. Per suggestion below it is undefined behavior. Which is a term programmers use, and new folks do not understand well.

Upvotes: 1

Richard
Richard

Reputation: 61567

The problem is here:

s=s*2;

(Though you should be sure to always initialize your variables, e.g. s=0 before the loop.)

Integers don't have a special value for when the number gets larger than the storage type, so they overflow.

Here's an example of that could happen. Imagine that we store integers as a series of 4 bits where the first bit means that a number is negative. If we then begin counting in our system, we get the following:

0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = -0
1001 = -1
1010 = -2

So you can see that the numbers keep on growing inside the computer, but what they translate to suddenly becomes negative when the most significant bit is flipped on.

Computers use all kinds of different schemes for storing negative numbers, but Two's Complement is common. It's more clever than the system I've used to explain things here, but the essential point remains the same: when numbers get too big they become negative. In the case of an int the cross-over point is often when you hit 2^31, or 2147483648.

A workaround is to use unsigned int, which roughly doubles the largest number you can represent, or long, long long, unsigned long, or unsigned long long. Remember, this won't solve your problem, it will just give you larger numbers you can work with before a problem appears.

You can find the largest usable value using the limits.h header file; for an int it is INT_MAX.

Upvotes: 4

Related Questions