-3

This is the program to check whether given number is Armstrong number or not

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>

int main(int argc, char *argv[])
{   
    int num,n,sum=0;
    num=atoi(argv[1]);
    if(argc==2 && num>0 && num<=INT_MAX)    
    {   n=num;
        while(num>0)
        {
            sum+=(num%10)*(num%10)*(num%10);
            num/=10;
        }
        if(sum==n)
            printf("%d is an armstrong number",n);
        else    
            printf("%d is not an armstrong number",n);
        return 0;    
    }
    else
        return 1;
}

Here i gave an input

-12345678969

expected output

Command exited with non-zero status 1

but it shows

539222919 is not an armstrong number

alk
  • 69,737
  • 10
  • 105
  • 255
Aksh
  • 71
  • 1
  • 7
  • See `INT_MIN` in `limits.h` `int` can't store any value that won't fit in... well, whatever size an `int` is on your platform, and this number is outside that range. If you used `long`s instead of `int`s, you wouldn't have this particular problem. – Charles Duffy Feb 17 '18 at 15:00
  • Compile with all warnings and debug info, e.g. `gcc -Wall -Wextra -g` with [GCC](http://gcc.gnu.org/). [use the `gdb` debugger](https://sourceware.org/gdb/current/onlinedocs/gdb/) – Basile Starynkevitch Feb 17 '18 at 15:00
  • 1
    ...for example, on MacOS X, `/usr/include/i386/limits.h` defines `INT_MIN` as `(-2147483647-1)`; notably, `-12345678969` is smaller than that, so it can't be stored in an `int`. – Charles Duffy Feb 17 '18 at 15:02
  • BTW, `int` is generally 32 bits. You might want [bignums](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) (or at least [`int64_t`](http://en.cppreference.com/w/c/types/integer)...). Consider [GMPlib](http://gmplib.org/) – Basile Starynkevitch Feb 17 '18 at 15:03
  • 2
    `num <= INT_MAX` is meaningless if `num` is an `int`. It **can't possibly** be assigned a value outside the realm of what an `int` can store, because, well, *it's an `int`*. – Charles Duffy Feb 17 '18 at 15:04
  • 5
    See also [Why shouldn't I use `atoi`?](https://stackoverflow.com/questions/17710018/why-shouldnt-i-use-atoi); compare to `strtol`, which has well-defined underflow and overflow behaviors, and provides a means to detect errors (which, for example, [this answer](https://stackoverflow.com/a/24599796/14122) demonstrates). – Charles Duffy Feb 17 '18 at 15:05
  • Possible duplicate of [Often big numbers become negative](https://stackoverflow.com/questions/17218964/often-big-numbers-become-negative) – tripleee Feb 17 '18 at 15:12
  • Possible duplicate of [Why shouldn't I use atoi()?](https://stackoverflow.com/questions/17710018/why-shouldnt-i-use-atoi) – Andrew Henle Feb 17 '18 at 15:25

2 Answers2

4

The number '-12345678969' requires too many bits for an int. An int in most C compilers is 32-bits wide, however that is not enough bits to be able to contain '-12345678969'.

atoi() simply tries to convert the number to a 32-bit integer, meaning a part of the input value of '-12345678969' is cut off; In base 2 (binary) representation the input number would fit in a 64-bit integer as:

1111111111111111111111111111110100100000001000111110001110000111

And when atoi() cuts off the high order 32 bits, the low order 32 bits remain:

00100000001000111110001110000111

which contains no sign any more (the bit you read first from the left is 0, meaning there is no sign and thus the number is not negative in a signed int).

That number in decimal representation would be equal to 539222919, which is the number you see in your case.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Bas Groothedde
  • 402
  • 4
  • 8
  • 2
    More on that concept: https://en.wikipedia.org/wiki/Integer_overflow And interesting historical reference to integer overflow: http://www-users.math.umn.edu/~arnold/disasters/ariane.html – Simon Berthiaume Feb 17 '18 at 15:15
2
-12345678969

in hex is

0xFFFFFFFD2023E387

(each digit represents 4 bits)

atoi() returns an int, which mostly likely is 32 bits.

Taking the least significant 32 bits of 0xFFFFFFFD2023E387 gives us 0x2023E387 which in fact is

539222919 

in decimal.

alk
  • 69,737
  • 10
  • 105
  • 255
  • Yo won't believe what happened now. I just was using `-123456789` and not getting same as you. Should be more awake. Yes I was aware of that..just trying to find where I was going wrong – user2736738 Feb 17 '18 at 15:45
  • @coderredoc: Just memorise that 4 000 000 000 and bit soon breaks the (unsigned) 32bit barrier .... :-) – alk Feb 17 '18 at 15:48
  • .: `4000 000 000` what do you mean? – user2736738 Feb 17 '18 at 15:51
  • @coderredoc: I mean the number 4000000000 is nearly equal to the maximum you can store using 32 bits. If you memorised this you would not have assumed 123456789 (which obviously is much smaller then 4000000000) to be a relevant value in this context, you would not have made the mistake you mentioned. ;-) – alk Feb 17 '18 at 15:55
  • .: I see...the decimal 4000..00 - I will remmeebr it. Yep. If it was -123456789 then also it would fit in. – user2736738 Feb 17 '18 at 15:57