2013年2月3日 星期日

[C Programming] Armstrong數-延伸

請參照Armstrong數
延伸:
如果是要寫出輸入n的位數,求出所有n位數的數字,
等同於其每一位的n次方的和的Armstrong數呢?
可以不要用到exp(), log()等函數嗎?
資料型別要注意什麼?

解:
運用之前個人的方式,
先將0~9的n次方存起來,
接著再將每個位數一次一次拆解以後取對應的n次方值加總。
用這個方法我們也可以算從1位到n位的Armstrong數。
只要運用迴圈,就可以有效的利用0~9的n次方值。
資料型別的部分,
由於C內建最長的型態應該是unsigned long long int,
其大小為2^64 - 1 = 18446744073709551615
而最長的Armstrong數為:

No.88 11513 22190 18763 99256 50955 97973 97152 2401

有36位,所以其實以內建的長度來說只能到20位。
但......跑到10位左右其實就已經會花很長的時間了,
我相信除了閒著沒事的人應該不需要它才是Orz......

使用long long int的話,printf的參數為%lld,
unsigned long long int的話應該是%llu。(若有錯請不吝指正)

下面Code分成只算單n位的,以及從1位數算到n位的Armstrong數。

單n位的Armstrong數:
int armstrong(int n)
{
 unsigned long long int sum, num, i, ubnd=9, lbnd=1;
 int count, quoti, totalCnt = 0;
 unsigned long long int* uniE = 
   (unsigned long long int*)
     malloc(sizeof(unsigned long long int)*10);
 for(count = 0; count <= 9; count++)
  uniE[count] = count;
 for(count = 2; count <= 9; count++)
  for(i = 2;i <= n; i++)
   uniE[count] *= count;
 for(i = 2; i <= n; i++)
 {
  lbnd *= 10;   // lower_bound為1 00.....0
  ubnd += 9*lbnd;  // upper_bound為9 99.....9
 }
 for(i = lbnd; i <= ubnd; i++)
 {
  num = i; sum = 0;
  while(num != 0)
  {
   quoti = num % 10; // 每次取個位數加入指數和 
   num /= 10;
   sum += uniE[quoti];
  }
  if(sum == i)
   printf("%d:  %llu\n", ++totalCnt, i); 
 }
 free(uniE); uniE = 0;
 return totalCnt;
}
從1位算到n位的Armstrong數:
int armstrong(int n)
{
 unsigned long long int sum, num, i, ubnd=9, lbnd=1;
 int count, quoti, digitCnt = 1, totalCnt = 0;
 unsigned long long int* uniE = 
   (unsigned long long int*)
            malloc(sizeof(unsigned long long int)*10);
 uniE[0] = 0;
 for(count = 1; count <= 9; count++)
 {
  uniE[count] = count;
  printf("%2d:  %d\n", ++totalCnt, count); // 1~9直接輸出
 }
 while(++digitCnt <= n)
 {
  for(count = 2; count <= 9; count++) // 指數單位更新
   uniE[count] *= count;
  
  lbnd *= 10;   // lower_bound為1 00.....0
  ubnd += 9*lbnd;  // upper_bound為9 99.....9
  
  for(i = lbnd; i <= ubnd; i++)
  {
   num = i; sum = 0;
   while(num != 0)
   {
    quoti = num % 10; // 每次取個位數加入指數和 
    num /= 10;
    sum += uniE[quoti];
   }
   if(sum == i)
    printf("%d:  %llu\n", ++totalCnt, i); 
  }
 }
 free(uniE); uniE = 0;
 return totalCnt;
}

沒有留言:

張貼留言