I'm trying to write a code that finds armstrong numbers, but it outputs a huge number.

if trying to write a code that has to type two variables n and m, and then output all armstrong numbers(numbers that equal their digits to the power of number of digits) between n and m (inclusive), but it only outputs the same very large number.
(Is there a common cause for programs outputting very large numbers?)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  #include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n,m,ii,sum;
    while(cin>>n>>m)
    {
        int k=0,a[1000];
        for(int i=n;i<=m;i++)
        {
            ii=i;
            sum=0;
            int b[10],h=0;
            for(int j=6;j>=0;j--)
            {
                b[6-j]=ii/pow(10,j);
                if(h=0&&ii/pow(10,j)!=0)
                    h=j;
                ii-=pow(10,j);
            }
            for(int l=h;l>=0;l--)
            {
                sum+=pow(b[l],h+1);
            }
            if(sum==i)
            {
                a[k]=sum;
                k++;
            }
        }
        if(a[0]==0)
            cout<<"none"<<endl;
        else
        {
            for(int o=0;o<=k;o++)
                cout<<a[o]<<' ';
            cout<<endl;
        }
    }
}
I've no idea if there's some method but the brute force to calculate those numbers, but having read about what they are
https://en.wikipedia.org/wiki/Narcissistic_number
your code looks unnecessary complicated. Is that an optimization against brute force?

It seems that what you need is
- a loop between to limits;
- a number n which increments at every iteration;
- at every iteration:
    - get the number of digits of ‘n’ --> n_digits;
    - calculate the sum of the digits raised to ‘n_digits’;
    - check if that sum is equal to ‘n’.


To get the number of digits, you can use std::log10();
To get each digit, you can use modulo operator.

Honestly, it looks like you can solve it in a few rows of code.

Anyway, you can try with long long to get to higher numbers.
Last edited on
how exactly do i get the digits using modulo?
does division with int cause problems?
Last edited on
(i feel defeated that i have to ask a question that is the basics of the basics of the basics for decent programmers ughhhhh)
Suppose you check the number 101. The first time through the loop, line 17 extracts the millions digit, which is 0. Then line 20 subtracts 1 million. leaving -999899. Now you're completely off the rails. The problem is that you started with the wrong digit.

The same sort of problem occurs if you check a 7 digit number: the first "digit" will be greater than 10.

Also, at line 32, if you found no Armstrong numbers then the a[0] will be uninitialized, not zero. So you'd have to initialize it to zero.

Overall you've made this more complicated than it needs to be:
- Why store the results? Why not just print them as you see them?
- Why extract the digits from the left? It's much easier to extract them from the right?
- Why store the digits from the left? Since the Armstrong calculation doesn't depend on the order of the digits, you can store them in any order.

Here's a version that extracts the digits from the right and stores then in the order extracted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

// Extract the digits in num and return them in a vector
vector<int> getDigits(int num)
{
    vector<int> result;
    while (num) {
	result.push_back(num % 10);
	num /= 10;
    }
    return result;
}

// Given the digits of a number, compute the sum of the digits raised
// to the size of the number.
int armstrongCalc(const vector<int> &digits)
{
    int result = 0;
    for (int digit : digits) {
	result += pow(digit, digits.size());
    }
    return result;
}

int
main()
{
    int n, m;
    while (cin >> n >> m) {
	for (int i = n; i <= m; i++) {
	    vector<int> digits = getDigits(i);
	    if (armstrongCalc(digits) == i) {
		cout << i << '\n';
	    }
	}
    }
}

This runs but it's kind of slow. It could be sped up dramatically by precomputing the powers of the digits.
Recursion practice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

unsigned ipow( unsigned n, unsigned p ) { return p ? n * ipow( n, p  - 1 ) : 1; }

unsigned sumDigitsPower( unsigned n, unsigned p ) { return n ? ipow( n % 10, p ) + sumDigitsPower( n / 10, p ) : 0; }

unsigned numDigits( unsigned n ){ return n < 10 ? 1 : 1 + numDigits( n / 10 ); }

bool isNarcissistic( unsigned n ) { return sumDigitsPower( n, numDigits( n ) ) == n; }

int main()
{
   const unsigned L = 1, H = 999999;
   for ( unsigned n = L; n <= H; n++ ) if ( isNarcissistic( n ) ) cout << n << " ";
}




But @dhayden is right: it's faster if you precompute the powers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
using namespace std;

unsigned numDigits( unsigned n ){ return n < 10 ? 1 : 1 + numDigits( n / 10 ); }

int main()
{
   // Precompute powers
   const int MAXPOWER = 8;
   int powers[10][MAXPOWER+1] = { 0 };
   for ( int i = 1; i <= 9; i++ )
   {
      powers[i][0] = 1;
      for ( int p = 1; p <= MAXPOWER; p++ ) powers[i][p] = i * powers[i][p-1];
   }

   // Scan numbers from L to H
   const unsigned L = 1, H = 999999;
   for ( unsigned number = L; number <= H; number++ )
   {
      unsigned n = number;
      unsigned p = numDigits( n );
      unsigned sum = 0;
      while ( n )
      {
         sum += powers[n%10][p];
         n /= 10;
      }
      if ( sum == number ) cout << number << " ";
   }
}
Last edited on
Topic archived. No new replies allowed.