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

Mar 10, 2019 at 11:32am
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;
        }
    }
}
Mar 10, 2019 at 12:40pm
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 Mar 10, 2019 at 12:41pm
Mar 10, 2019 at 1:31pm
how exactly do i get the digits using modulo?
does division with int cause problems?
Last edited on Mar 10, 2019 at 2:09pm
Mar 10, 2019 at 1:49pm
(i feel defeated that i have to ask a question that is the basics of the basics of the basics for decent programmers ughhhhh)
Mar 10, 2019 at 2:21pm
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.
Mar 10, 2019 at 5:33pm
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 Mar 10, 2019 at 8:22pm
Topic archived. No new replies allowed.