計算機プログラムの構造と解釈(SICP)学習メモ
蒋 いつ峰 2008/07/15   |  プログラミング基礎
第一章 練習1.16〜1.18 冪乗、積を求める 2008/07/15  |  PK:SICP 練習 1.16、1.17、1.18

再帰と反復で冪乗、積を求める。


問題

SICPの練習 1.16:反復で b の n 冪乗を求める。時間コストは log(n) でなければ成らない。
練習 1.17:「足す、倍、半分」を用いて「積」を求める。時間コストは log(n) でなければ成らない。
練習 1.18:「足す、倍、半分」を用いて、反復法で「積」を求める。。時間コストは log(n) でなければ成らない。


解答

 
  1. /** 
  2.  * SICP練習1.16〜1.18 
  3.  */  
  4.   
  5. import std.stdio;  
  6.   
  7. /** 
  8.  * 練習1.16。 
  9.  * 反復で b の n 冪乗を求める。 
  10.  * 時間コストは log(n) でなければ成らない。 
  11.  */  
  12. int fastExpt(int b, int n) {      
  13.     int a = 1;  
  14.     a = iter(b, n, a);  
  15.     return a;  
  16. }  
  17.   
  18. int iter(int b, int n, int a) {  
  19.     writefln("b = %d, n = %d, a = %d", b, n, a);  
  20.     if (n == 0) {  
  21.         return a;  
  22.     } else if (n % 2 == 0) {  
  23.         return iter(b * b, n / 2, a);  
  24.     } else {  
  25.         return iter(b, n - 1, a * b);  
  26.     }  
  27. }  
  28.   
  29.   
  30. /** 
  31.  * 練習1.17。 
  32.  * 「足す、倍、半分」を用いて「積」を求める。 
  33.  * 時間コストは log(n) でなければ成らない。 
  34.  */  
  35. int fastMulti(int b, int n) {  
  36.     if (n == 0) {  
  37.         return 0;  
  38.     } else if (n == 1) {  
  39.         return b;  
  40.     } else {  
  41.         if (n % 2 == 0) {  
  42.             return fastMulti(doulbe(b), halve(n));  
  43.         } else {  
  44.             return b + fastMulti(b, n - 1);  
  45.         }  
  46.     }  
  47. }  
  48.   
  49. /** 
  50.  * 練習1.18。 
  51.  * 「足す、倍、半分」を用いて、反復法で「積」を求める。 
  52.  * 時間コストは log(n) でなければ成らない。 
  53.  */  
  54. int fastMulti2(int b, int n) {  
  55.     int a = 0;  
  56.     a = iter2(b, n, a);  
  57.     return a;  
  58. }  
  59.   
  60. int iter2(int b, int n, int a) {  
  61.     writefln("b = %d, n = %d, a = %d", b, n, a);  
  62.     if (n == 0) {  
  63.         return a;  
  64.     } else if (n % 2 == 0) {  
  65.         return iter2(doulbe(b), halve(n), a);  
  66.     } else {  
  67.         return iter2(b, n - 1, a + b);  
  68.     }  
  69. }  
  70.   
  71. int doulbe(int a) {  
  72.     return a + a;  
  73. }  
  74.   
  75. int halve(int a) {  
  76.     // a は偶数とする  
  77.     return a / 2;  
  78. }  
  79.   
  80. void main() {  
  81.     // for 1.16  
  82.     int b = 2;  
  83.     int n = 10;  
  84.   
  85.     writefln("\n---- 1.16 ----");  
  86.     int ret = fastExpt(b, n);  
  87.     writefln("\nfastExpt(%d, %d) = %d", b, n, ret);  
  88.   
  89.     // for 1.17  
  90.     ret = fastMulti(b, n);  
  91.     writefln("\n---- 1.17 ----");  
  92.     writefln("fastMulti(%d, %d) = %d", b, n, ret);  
  93.   
  94.     // for 1.18  
  95.     writefln("\n---- 1.18 ----");  
  96.     ret = fastMulti2(b, n);  
  97.     writefln("\nfastMulti2(%d, %d) = %d", b, n, ret);  
  98. }  

実行結果:

uprush@uprush-dev:~/src/d/sicp$ ./q1_16_1_18

---- 1.16 ----
b = 2, n = 10, a = 1
b = 4, n = 5, a = 1
b = 4, n = 4, a = 4
b = 16, n = 2, a = 4
b = 256, n = 1, a = 4
b = 256, n = 0, a = 1024

fastExpt(2, 10) = 1024

---- 1.17 ----
fastMulti(2, 10) = 20

---- 1.18 ----
b = 2, n = 10, a = 0
b = 4, n = 5, a = 0
b = 4, n = 4, a = 4
b = 8, n = 2, a = 4
b = 16, n = 1, a = 4
b = 16, n = 0, a = 20

fastMulti2(2, 10) = 20


閲覧  |  コメント  |  目次

 
ヘルプ  |  ご利用規約  |  相互リンク  |  問合せ
リンクはご自由に、問合せはお気軽に
©2007 Uprush