0

I am learning to code in C and need to get more familiar with overflow and dealing with large numbers. I need help dealing with the below code. This isn't my desired output as when I do the calculations on my own, the negative numbers are incorrect. I know it has to do with the larger numbers I'm dealing with. How do I go about approaching this problem? I'm not to sure where to start?

Thanks!

int main() {
    unsigned A = 1103624256;
    unsigned B = 11254;
    unsigned X = 1;
    unsigned max_unsigned = (long)(UINT_MAX);
    X = ((A*X)+B)%max_unsigned;
    printf("X1 =\t%d\n", X);
    X = ((A*X)+B)% max_unsigned;
    printf("X2 =\t%d\n",X);
    X = ((A*X)+B)%max_unsigned;
    printf("X3 =\t%d\n", X);
    X = ((A*X)+B)% max_unsigned;
    printf("X4 =\t%d\n",X);
    return 0;
}

my output is:

X1 =    1103635510
X2 =    823626102
X3 =    -473507466
X4 =    -1793402506
Program ended with exit code: 0
Barmar
  • 741,623
  • 53
  • 500
  • 612
Nadine
  • 11
  • 1
  • You can't use a 32-bit type to hold the entire range of both signed `int` and `unsigned int` but you can use a larger type, such as `long long`. – Weather Vane Mar 20 '20 at 16:30
  • Should I cast all variables to long long? – Nadine Mar 20 '20 at 16:32
  • When the calculation overflows, you get implementation-dependent results, often a negative number. And negative % positive returns a negative number. – Barmar Mar 20 '20 at 16:32
  • Cast one of the variables in `A*X` to `long long`, then it will propagate to the rest of the expression. – Barmar Mar 20 '20 at 16:33
  • Instead of using `%max_unsigned` you need to use `&max_unsigned` because the former will only produce values from [`0`, `max_unsigned`) (or `0` to `max_unsigned - 1`). – S.S. Anne Mar 20 '20 at 17:06

1 Answers1

0

Unsigned Int uses quite often 32 bits. That means, the biggest representable number is 4294967296. This is then max_unsigned in your code.

Your first calculation X = ((A*X)+B)%max_unsigned is therefore 1103624256*1+11254%4294967296=1103635510, which is the result, you are seeing.

In your second calculation the expression A*X is then too big to fit into 32 bits.

That means, your code is illegal, because you do an illegal calculation. This is not covered by the C++ language standard. For example see here: https://en.cppreference.com/w/cpp/language/operator_arithmetic :

When signed integer arithmetic operation overflows (the result does not fit in the result type), the behavior is undefined.

That really means, that anything can happen. The program could behave on Mondays as you expect and on Tuesdays not. The program may crash. Your computer may crash. Your result may be incorrect. The behaviour is just not part of the language specification for C. And therefore the answer to your question must end here. That is the reason why for two years there is not even one answer to the question.

It may be the case that on certain platforms and certain compilers it is possible to predict the behaviour. And you may want to look at the Assembler code to see what happens. But all this is then outside the scope of the C language and therefore not of general interest. C is not a specification language for creating Assembler code. C has rules that must be followed. Otherwise you are not in the scope of C.

It would also not be very professional to speculate more, because in a professional environment you are normally paid to follow rules. And that includes the rules of the programming language.

If you are really interested to see what happens, you have to show the Assembler code and make it a question about Assembler programming. But there is no guarantee that your compiler always produces the same Assembler code for such illegal things. The compiler only guarantees you a predictable result if you follow the rules of the programming language and have no overflows.

habrewning
  • 735
  • 3
  • 12