1. 程式人生 > >18.12.09-C語言練習:黑洞數 / Kaprekar問題

18.12.09-C語言練習:黑洞數 / Kaprekar問題

 

題目:

程式:

 1 #include <stdio.h>
 2 
 3 int main(void) {
 4     int n, a, b, c, t, A, B;
 5     printf("輸入一個三位數整數:");
 6     scanf("%d",&n);
 7     do{
 8         /*a, b, c 分別是百位數,十位數,個位數*/
 9         a = n/100;
10         b = (n%100)/10;
11         c = (n%10);
12         /* 百位數,十位數,個位數按照從大到小的順序重排,以便下一步中求重排後的最大值A和最小值B
*/ 13 if(a<b) { 14 t = a; a = b; b = t; 15 } 16 if(a<c) { 17 t = a; a = c; c = t; 18 } 19 if(b<c) { 20 t = b; b = c; c = t; 21 } 22 /*從排後的最大數A與最小數B*/ 23 A = a * 100 + b * 10 + c; 24 B = c * 100
+ b * 10 + a; 25 /*將最大數與最小數的差,重新賦給變數n,以便做迴圈判斷或下次迴圈使用*/ 26 n = A - B; 27 /*輸出過程*/ 28 printf("%d - %d = %d\n", A, B, n); 29 } while(n!=495 && n!=0); 30 return 0; 31 }

程式說明:

1. 程式大體思路可以看程式中註釋,大體分為兩個步驟:輸入和迴圈中計算。其中迴圈中計算過程分為這麼幾個步驟:求個位十位百位上三個數字;個位十位百位三個數字按從大到小排列;求得重排後的最大值和最小值;求差和輸出。

2. 難點在於:(1)求個位十位百位數字;(2)確定迴圈變數n;(3)黑洞數演算法計算過程的程式表達。

3. 關於迴圈變數n: 因為演算法中要求的是重排後數字的最大值與最小值之差。所以n是迴圈變數。

執行結果:

 

錯誤程式:

 

錯誤或可優化部分分析:

1. (錯誤)變數名混用導致棋藝:c和C混用了,難以分清c 和C的具體含義。根據程式理解可能是:(1)個位十位百位三個數字中的一個。(好像小寫c是這個意思);(2)重排後的差。(好像大寫C是這個意思)。但在while迴圈判斷的時候用錯了。

2. (可能是錯誤)個位十位百位計算過程應該向上移動若干行:這裡是否是個錯誤,主要看你對演算法實現的過程,還有就是演算法中的迴圈變數使用的是哪個。

3. (可優化)定義的變數最好不要用double:因為這裡要求的數字範圍總是整數,並且不超過3位數,所以用 int 型別最方便。用double雖然不算錯誤,但會在計算過程中轉化為int型別,所以用double沒必要。在具體程式中根據具體型別選擇適當的資料型別即可,不必使用更寬範圍的型別。

4. (可優化)求個位、十位、百位數字計算的優化:(假設表示式中用的是重排後的差,下面說明中我改成了大寫C)

 a = ((int)C/100)%10   (int)C/100 結果是百位數之前的部分,因為C是三位數,所以(int)C/100結果是百位數。因為C是三位數,雖然這裡沒錯但沒必要再進行 %10 求餘。

另外就是因為定義C是double型別,實際計算是用int型別,所以這裡使用了強制型別轉換,反而更麻煩。