116
交交交交 交交交 Sqrt-funBinary-1 Programming Concept 蔡蔡蔡 [email protected] 蔡蔡蔡蔡蔡蔡蔡蔡蔡蔡

Programming Concept

  • Upload
    riva

  • View
    86

  • Download
    5

Embed Size (px)

DESCRIPTION

Programming Concept. 蔡文能 [email protected] 交通大學資訊工程學系. http://www.csie.nctu.edu.tw/~tsaiwn/course/introcs/. 程式 隨便寫 隨便對 . ftp://ftp.csie.nctu.edu.tw/pub/CSIE/course/cs2/. 蔡文能 [email protected] 交通大學資訊工程學系. 平方根 – 簡 單演算法 九九乘法表 for Loop vs. while Loop Pascal Triangle - PowerPoint PPT Presentation

Citation preview

交大資工 蔡文能 Sqrt-funBinary-1

Programming Concept

蔡文能[email protected]交通大學資訊工程學系

交大資工 蔡文能 Sqrt-funBinary-2

程式 隨便寫 隨便對

蔡文能[email protected]

交通大學資訊工程學系

http://www.csie.nctu.edu.tw/~tsaiwn/course/introcs/

ftp://ftp.csie.nctu.edu.tw/pub/CSIE/course/cs2/平方根 – 簡單演算法九九乘法表for Loop vs. while LoopPascal Triangle二進位也可以很有趣 -- 如何印出該六張卡片 ?

交大資工 蔡文能 Sqrt-funBinary-3

印出根號 2 /* 寫個程式印出根號 2 */#include<stdio.h>double sqrt(double); // #include<math.h> int main( ) { printf(" sqrt 根號 2 =%f\n ", sqrt(2.0) ); // C++ 式的註解 comment printf("Bye bye!\n"); return 0; } sqrt 是程式庫裡的一個

函數 (function, 函式 )

C 型式的註

C++ 型式的註解

交大資工 蔡文能 Sqrt-funBinary-4

印出根號 3 /* 寫個程式印出根號 3 */#include<stdio.h>double sqrt(double); // #include<math.h> int main( ) { printf(" sqrt 根號 3 =%f\n ", sqrt(3.0) ); // C++ 式的註解 comment printf("Bye bye!\n"); return 0; } 每次要重改程式嗎 ?

交大資工 蔡文能 Sqrt-funBinary-5

印出根號 x /* 寫個程式印出根號 x */ #include <stdio.h> #include<math.h> double y; int main( ) { printf(" Give me x :" ); scanf("%lf " , &y); printf("Sqrt(%f)=%f\n", y, sqrt(y) ); return 0; }

使用變數

&y 傳 address

交大資工 蔡文能 Sqrt-funBinary-6

程式 隨便寫 求 x 的平方根

蔡文能[email protected]

交通大學資訊工程學系

file:///c:\course\cs2\file:///c:\course\cs2\p3.c

練習使用 while loop

交大資工 蔡文能 Sqrt-funBinary-7

p3.c – 練習 while loop#include <stdio.h>#include <math.h>int main()/* This program can find square root of any number that >=0 and will stop when you enter a value that < 0 阿版權是蔡文能的 , 歡迎拷貝分享初學者 ! */{ float onevar; /* 變數名稱隨便我取的啦 */ double ans; /* 用來放答案 */ printf("Find square root of X. Negative value will cease the program\n"); printf("X=? "); /* 還是問 "X=?" 比較簡潔有力 , 不用說 onevar */ scanf("%f", &onevar); while(onevar >=0 ) { /* 只要 onevar 大於或等於零我們就一直重複做 {...} */ ans=sqrt(onevar); /* 其實 sqrt 的參數也應該為 double 型別 */ printf(" SQRT(%f)=%f\n", onevar, ans); printf("X=? "); scanf("%f", &onevar); } /* while(onevar */ return 0;}

交大資工 蔡文能 Sqrt-funBinary-8

程式 隨便寫 求 x 的平方根

自己如何寫求 SQRT? file:///c:\course\cs2\p4.c file:///c:\course\cs2\p5.c

自己如何寫求 SQRT?

目的 : 練習 想 Algorithm

長除法求平方根 ?

適合手動做的方法不一定適合電腦做 !

交大資工 蔡文能 Sqrt-funBinary-9

p4.c – 練習 想 Algorithm(1/2)/* This program can find square root of any number that >=0 and will stop when you enter a value that < 0 *//* This version is trying to show you that we can write our function/procedure to solve the problem, though the mysqrt() is actually calling the system standard function. We will rewrite the mysqrt() in next version. *****************************/void hello(void); /* 我會用到一個沒參數的函數叫 hello() */double mysqrt(double); /* 也會叫用一個叫 mysqrt() 的函數 , 參數是一個 double 數 */#include <math.h> /* sqrt() 是在 math.h 內宣告的 */int main() /* 主程式開始囉 */{ float x; hello(); /* give the user some message */ printf("X=? "); scanf("%f", &x); while(x >=0 ) { printf(" SQRT(%f)=%7.3f\n", x, mysqrt(x) ); printf("X=? "); scanf("%f", &x); } /* while */ return 0;} /************** 主程式到此為止 ***********/

交大資工 蔡文能 Sqrt-funBinary-10

p4.c – 練習 想 Algorithm(2/2)/*…*/

void hello()

{

printf("This program will ask you to input a value, say X.");

printf("Then it will find the square root of X.");

printf("The above process will continue ...");

printf("Negative value will cease the program.");

} /* hello() */

double mysqrt(double y)

{

double myans;

myans = -1.0;

if(y < 0) printf(" can not process negative number");

else myans = sqrt(y); /* 還沒想好 , 先借用程式庫的 sqrt( ) */

return myans;

} /*mysqrt*/

交大資工 蔡文能 Sqrt-funBinary-11

p5.c – mysqrt( ) Algorithm(1/2)void hello(void); /* 我發誓我會用到一個沒參數的函數叫 hello() */

double mysqrt(double); /* 也會叫用一個叫 mysqrt() 的函數 , 參數是一個 double 數 */

int main() /* 主程式開始囉 */

{

float x;

hello(); /* give the user some message */

printf("X=? ");

scanf("%f", &x);

while(x >=0 ) {

printf(" SQRT(%f)=%7.3f\n", x, mysqrt(x) );

printf("X=? "); scanf("%f", &x);

} /* while */

return 0;

} /************** 主程式到此為止 ***********/

void hello()

{

printf("This program will ask you to input a value, say X.");

printf("Then it will find the square root of X.");

printf("The above process will continue ...");

printf("Negative value will cease the program.");

} /* hello() */

交大資工 蔡文能 Sqrt-funBinary-12

p5.c – mysqrt( ) Algorithm(2/2)double mysqrt(double x)

{ /* 這次真的要自己寫求平方根的部份囉 ! */

double myans;

myans = -1;

if(x < 0) printf(" can not process negative number\n");

else {

myans = 0; /* we guess the root is zero */

while(myans*myans < x) myans++; /* 猜 0, 1, 2,... 直到太大 */

if(myans*myans>x){

myans =myans-1; /* 太大了 , 快減掉一 ; 可寫成 myans--*/

while(myans*myans < x) myans = myans+0.1;

};

if(myans*myans>x){

myans-=0.1; /* this means : myans = myans -0.1 */

while(myans*myans < x) myans += 0.01;

}

if(myans*myans>x){

myans -= 0.01;

while(myans*myans < x) myans += 0.001;

}

/* I think the precison is good enought now */

} /*else*/

return myans; /** return myans value as our answer */

} /* end of mysqrt*/

交大資工 蔡文能 Sqrt-funBinary-13

mysqrt( ) 問題與思考 ?

• 若想要求到更準呢 ?• 這程式中函數 mysqrt( ) 所求出的平方根

若非剛好就會太大 , 這並非最好的做法 !• 應該找出最接近的答案 , 例如 , 求 2 的

平方根時 , 最後應考慮 1.415*1.415 與 1.414*1.414 何者較接近 2, 如此比較合理 ! 加一句 if 檢查看看就可以 , 想一想 !

交大資工 蔡文能 Sqrt-funBinary-14

程式 隨便寫 九九乘法表file:///c:\course\cs2\p6.c

練習兩層的 for loop

for(i=1; i<=9; ++i) {

for(k … ) {

/****/

}

}

交大資工 蔡文能 Sqrt-funBinary-15

九九乘法表 p6.c#include <stdio.h>int main(){ int i,j; printf("\nX |"); for(i=1; i <= 9; i++) printf("%5d", i); printf("\n"); for(i=1 ; i <= 10 ; i++) printf("---- "); for(i=1 ; i<= 9 ; i++) { printf("\n%d |" , i); for(j=1 ; j <= 9 ; j++) printf("%5d", i*j); } printf("\n======\n"); return 0;}

練習兩層的 for loop

交大資工 蔡文能 Sqrt-funBinary-16

九九乘法表 p6.c 核心#include <stdio.h>int main(){ int i,k; for(i=1 ; i<= 9 ; i++) { printf(" 第 %d 列 : " , i); for(k=1 ; k <= 9 ; k++) printf("%5d", i*k); printf("\n"); } printf("\nBye bye!\n"); return 0;}

練習兩層的 for loop

交大資工 蔡文能 Sqrt-funBinary-17

for Loop vs. while Loopfor(i=1 ; i<= 9 ; i++){ /* Loop body */}

i=1;for( ; i<= 9 ; ){ /* Loop body */ i++;}

i=1;while( i<= 9 ){ /* Loop body */ i++;}

這三個寫法意義這三個寫法意義完全一樣完全一樣

交大資工 蔡文能 Sqrt-funBinary-18

for Loop vs. while Loop

for( ; ; ) ;

;while( ){ ; ;}

== 0

!= 0

交大資工 蔡文能 Sqrt-funBinary-19

while Loop

拿盤子 , 拿飲料 , 找好位子 ;while( 肚子還餓 ){ 吃一盤 ; 喝一杯 ; 喘一口氣 ;}結帳 ; 回家 ;

All you can eat !

交大資工 蔡文能 Sqrt-funBinary-20

while Loop (cont-1)

拿盤子 , 拿飲料 , 找好位子 ;while( 肚子還餓 ){ 吃一盤 ; if( 有急事 || 很飽了 )break; if( 不會渴 ) continue; 喝一杯 ; 喘一口氣 ;}結帳 ; 回家 ;

All you can eat !

交大資工 蔡文能 Sqrt-funBinary-21

while Loop (cont-2)

拿盤子 , 拿飲料 , 找好位子 ;while( 不夠本 ){ 吃一盤 ; if( 有急事 || 很飽了 )break; if( 不會渴 ) continue; 喝一杯 ; 喘一口氣 ;}結帳 ; 回家 ;

交大資工 蔡文能 Sqrt-funBinary-22

p7.c 巴斯卡三角形練習 Array ( 陣列 )

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

(a+b)2 = a2+2a.b+b2

C(5,0) = 1 C(5,1) = 5 C(5,2) = 10 = C(5,3)

By Blaise Pascal, 1653

交大資工 蔡文能 Sqrt-funBinary-23

巴斯卡三角形 , 方便寫程式 0 1 2 3 4 5 6 7 8 . . . 0 1 1 1 1 2 1 2 1 i 3 1 3 3 1 4 1 4 6 4 1 5 1 5 10 10 5 1

int x[19][19];

int x[MAX][MAX];

#define MAX 19

交大資工 蔡文能 Sqrt-funBinary-24

p7.c 巴斯卡三角形 for(i=0; i<=n; i++) { x[i][0]=1; x[i][i] =1; /* 記得宣告 / 定義 x 陣列

喔 */

for(j=1; j<= i-1; j++) { x[i][j]= x[i-1][j] + x[i-1][j-1]; } for(j =0; j<=i; j++){ 1

printf("%5d", x[i][j]); 1 1 }; printf("\n"); 1 2 1 }; /* for i */ 1 3 3 1 1 4 6 4 1

i

第 j 格

交大資工 蔡文能 Sqrt-funBinary-25

問題與思考 (Pascal 三角形 ) 其實只用一維陣列 (one dimentional array)

就可以做出上述的巴斯卡三角形

Why? 因為是橫著填 .. 填完一列就可印出

• 程式要如何修改 ?

• 提示 : 中間的要由右而左填 ! • ? 巴斯卡三角形在數學上有哪些意義 ?

交大資工 蔡文能 Sqrt-funBinary-26

二進位也可以很有趣 想一個 0 到 63 間的任一個數 , 不要告訴我答案 ...

但是告訴我有沒有在以下哪幾張卡片中 ? 我可以很快找出來喔 !

交大資工 蔡文能 Sqrt-funBinary-27

二進位也可以很有趣

32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,48, 49, 50, 51, 52, 53, 54, 55,56, 57, 58, 59, 60, 61, 62, 63

交大資工 蔡文能 Sqrt-funBinary-28

二進位也可以很有趣

16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,48, 49, 50, 51, 52, 53, 54, 55,56, 57, 58, 59, 60, 61, 62, 63

交大資工 蔡文能 Sqrt-funBinary-29

二進位也可以很有趣

8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31,40, 41, 42, 43, 44, 45, 46, 47,56, 57, 58, 59, 60, 61, 62, 63

交大資工 蔡文能 Sqrt-funBinary-30

二進位也可以很有趣

4, 5, 6, 7, 12, 13, 14, 15,20, 21, 22, 23, 28, 29, 30, 31,36, 37, 38, 39, 44, 45, 46, 47,52, 53, 54, 55, 60, 61, 62, 63

交大資工 蔡文能 Sqrt-funBinary-31

二進位也可以很有趣

2, 3, 6, 7, 10, 11, 14, 15,18, 19, 22, 23, 26, 27, 30, 31,34, 35, 38, 39, 42, 43, 46, 47,50, 51, 54, 55, 58, 59, 62, 63

交大資工 蔡文能 Sqrt-funBinary-32

二進位也可以很有趣

1, 3, 5, 7, 9, 11, 13, 15,17, 19, 21, 23, 25, 27, 29, 31,33, 35, 37, 39, 41, 43, 45, 47,49, 51, 53, 55, 57, 59, 61, 63

交大資工 蔡文能 Sqrt-funBinary-33

二進位也可以很有趣 (原理 )

1, 3, 5, 7, 0 0 0 0 0 1 = 1 9, 11, 13, 15, 0 0 0 0 1 0 = 217, 19, 21, 23, 0 0 0 0 1 1 = 3 25, 27, 29, 31, 0 0 0 1 0 0 = 433, 35, 37, 39, 0 0 0 1 0 1 = 5 41, 43, 45, 47, 0 0 0 1 1 0 = 649, 51, 53, 55, 0 0 0 1 1 1 = 7 57, 59, 61, 63 0 0 1 0 0 0 = 8

交大資工 蔡文能 Sqrt-funBinary-34

二進位也可以很有趣 (原理 ) 2, 3, 6, 7, 0 0 0 0 0 1 = 1 10, 11, 14, 15, 0 0 0 0 1 0 = 218, 19, 22, 23, 0 0 0 0 1 1 = 3 26, 27, 30, 31, 0 0 0 1 0 0 = 434, 35, 38, 39, 0 0 0 1 0 1 = 5 42, 43, 46, 47, 0 0 0 1 1 0 = 650, 51, 54, 55, 0 0 0 1 1 1 = 7 58, 59, 62, 63 0 0 1 0 0 0 = 8

交大資工 蔡文能 Sqrt-funBinary-35

二進位也可以很有趣 (原理 ) 4, 5, 6, 7, 0 0 0 0 0 1 = 1 12, 13, 14, 15, 0 0 0 0 1 0 = 220, 21, 22, 23, 0 0 0 0 1 1 = 3 28, 29, 30, 31, 0 0 0 1 0 0 = 436, 37, 38, 39, 0 0 0 1 0 1 = 5 44, 45, 46, 47, 0 0 0 1 1 0 = 652, 53, 54, 55, 0 0 0 1 1 1 = 7 60, 61, 62, 63 0 0 1 0 0 0 = 8

交大資工 蔡文能 Sqrt-funBinary-36

二進位也可以很有趣 (原理 )

8, 9, 10, 11, 0 0 0 1 1 1 = 7 12, 13, 14, 15, 0 0 1 0 0 0 = 824, 25, 26, 27, 0 0 1 0 0 1 = 928, 29, 30, 31, 0 0 1 0 1 0 = 1040, 41, 42, 43, 0 0 1 0 1 1 = 11 44, 45, 46, 47, 0 0 1 1 0 0 = 1256, 57, 58, 59, 0 0 1 1 0 1 = 13 60, 61, 62, 63 0 0 1 1 1 0 = 14

交大資工 蔡文能 Sqrt-funBinary-37

二進位也可以很有趣 (原理 )16, 17, 18, 19, 0 1 0 0 0 0 = 16

20, 21, 22, 23, 0 1 0 0 0 1 = 17

24, 25, 26, 27, 0 1 0 0 1 0 = 18

28, 29, 30, 31, 0 1 0 0 1 1 = 19

48, 49, 50, 51, 0 1 0 1 0 0 = 20

52, 53, 54, 55, 0 1 0 1 0 1 = 21

56, 57, 58, 59, 0 1 0 1 1 0 = 22

60, 61, 62, 63 0 1 0 1 1 1 = 23

交大資工 蔡文能 Sqrt-funBinary-38

二進位也可以很有趣 (原理 )32, 33, 34, 35, 1 0 0 0 0 0 = 32

36, 37, 38, 39, 1 0 0 0 0 1 = 33

40, 41, 42, 43, 1 0 0 0 1 0 = 34

44, 45, 46, 47, 1 0 0 0 1 1 = 35

48, 49, 50, 51, 1 0 0 1 0 0 = 36

52, 53, 54, 55, 1 0 0 1 0 1 = 37

56, 57, 58, 59, 1 0 0 1 1 0 = 38

60, 61, 62, 63 1 0 0 1 1 1 = 39

交大資工 蔡文能 Sqrt-funBinary-39

卡片玩法與原理 請玩者心裡想一個 0 到 63 的整數不要告訴你 (廢話 ), 然後你依第六張、 第五張、第四張 ... 第一張拿給他 , 請他告訴你上面有沒有他想的數 , 為了表示你是過目不忘 , 交給他之前假裝看一看 , 交給他後不要立刻 拿回來 , 只請他分別放不同手中作為證據。

答案 : 如果六張都沒有就是 0。 在每張給他之前看清楚第一個數 , 只要他說有就加到答案中 , 等到 最後一張給他 , 等他說出有沒有後 , 答案也出來了。 原理 : 其實每張紙都是代表一個二進位數 (binary number)。 有就是 1, 沒有就是 0。 與上一遊戲一樣 , 他已經把答案告訴你了 ! 因每張紙上第一位數就是該位的比重 (weight, 加權 )。

交大資工 蔡文能 Sqrt-funBinary-40

二進位也可以很有趣 /* 寫程式印出前述之六張卡片 */ for( int i=0; i <= 5; i++) { printf(" 二進位也可以很有趣 \n\n ");

/* 印出第 i 張卡片 */

printf("\n\n\n"); }

交大資工 蔡文能 Sqrt-funBinary-41

二進位也可以很有趣 for( int i=0; i <= 5; i++) { printf(" 二進位也可以很有趣 \n\n "); for(k=0; k <= 63; k++) { if( k & (2 的 i 次方 ) != 0) { printf("%2d, ", k); if(必要時 ) printf("\n"); } } printf("\n\n\n"); }

?

交大資工 蔡文能 Sqrt-funBinary-42

int yy[ ] = { 1, 2, 4, 8, 16, 32};

for( int i=0; i <= 5; i++) { printf(" 二進位也可以很有趣 \n\n "); for(k=0; k <= 63; k++) { if( k & yy[i] != 0) { printf("%2d, ", k); if(必要時 ) printf("\n"); } } printf("\n\n\n"); } 用一個陣列記住 2 的 i 次方

?

交大資工 蔡文能 Sqrt-funBinary-43

if(必要時 ) printf("\n"); int np = 0; /* numbers printed */ for(k=0; k <= 63; k++) { if( k & yy[i] != 0) { printf("%2d, ", k); np++; // number printed if( np%8 == 0) printf("\n"); } }

?

交大資工 蔡文能 Sqrt-funBinary-44

if(必要時 ) printf("\n"); int np = 0; for(k=0; k <= 63; k++) { if( k & yy[i] != 0) { printf("%2d, ", k); /// np++; // number printed if( (++np)%8 == 0) printf("\n"); // 每印完八個數就換列 (new line) } }

?

交大資工 蔡文能 Sqrt-funBinary-45

二進位也可以很有趣完整程式 /* 寫程式印出前述之六張卡片 */#include<stdio.h>int yy[ ] = { 1, 2, 4, 8, 16, 32};int k, np;main( ) { for( int i=0; i <= 5; i++) { printf(" 二進位也可以很有趣 \n\n "); np=0; /* 印出第 i 張卡片 */ printf("\n\n\n"); } }

前一頁程式碼 for . .

交大資工 蔡文能 Sqrt-funBinary-46

問題與思考 * 為什麼要依第六張 (32 開頭那張 )、 第五張、 第四張 ... 第一張拿給玩者 ? * 如果不用一個 table (array) 來記住 2 的 i 次方 , 那要怎麼做 ? 用乘的 –– 有何缺點 ?

* 每張卡片最後一列也印了逗點 , 如何改進 ? (hint: 加一列 if )

交大資工 蔡文能 Sqrt-funBinary-47

問題與思考 (ASCII code )#include<stdio.h>main( ) { printf(" %c 的 ASCII code 是 %d\n", '0', '0'); printf(" %c 的 ASCII code 是 %d\n", 'A', 'A'); printf(" %c 的 ASCII code 是 %d\n", 'a', 'a');} 如果系統使用 EBCDIC 碼呢 ?

交大資工 蔡文能 Sqrt-funBinary-48

問題與思考 (ASCII code )#include<stdio.h>main( ) { int i, k=0; for(i=65; i<=122; ++i) { printf(" %c 的 ASCII code", i); printf(" 是 %d", i); ++k; printf(k%3==0? "\n" : "\t"); } printf("\n" );}

交大資工 蔡文能 Sqrt-funBinary-49

問題與思考 ( 中文碼 ?)#include<stdio.h>unsigned char x[9] = { 0 };main( ) { int m = 0xa4, n=0x6a; x[0] = m; x[1]=n; x[2] = 0xae, x[3]=97; x[4] = 0xa6, x[5]=0x6e; printf("==%s==\n", x);}

交大資工 蔡文能 Sqrt-funBinary-50

問題與思考 ( 中文碼 ?)

ccbsd2: tsaiwn> gcc testc.cccbsd2: tsaiwn> ./a.out== 大家好 ==

ccbsd2: tsaiwn>

先把前面程式存入 testc.c

交大資工 蔡文能 Sqrt-funBinary-51

實數與準確度 (precision)#include<stdio.h>float x, xdelta; int i; /*precision.c */main( ) { double y; x = 1234567.2, xdelta = 0.0001; printf("Before loop, x=%f\n", x); for(i=1; i<= 8000; i++){ y = x + xdelta; /******/ if(i == 1) printf("first y = %f\n", y); x = y; } printf("After loop, x=%f\n", x);}

交大資工 蔡文能 Sqrt-funBinary-52

float 實數準確度七位多

ccbsd2:precision/> gcc precision.c

ccbsd2:precision/> ./a.out

Before loop, x=1234567.250000

first y = 1234567.250100

After loop, x=1234567.250000

ccbsd2:precision/>

float 實數佔用 32 bits

交大資工 蔡文能 Sqrt-funBinary-53

double 實數準確度#include<stdio.h>double x, xdelta; int i; /*precdbl.c */main( ) { double y; x = 1234567.2, xdelta = 0.0001; printf("Before loop, x=%f\n", x); for(i=1; i<= 8000; i++){ y = x + xdelta; /******/ if(i == 1) printf("first y = %f\n", y); x = y; } printf("After loop, x=%f\n", x);}

交大資工 蔡文能 Sqrt-funBinary-54

double 實數準確十五位多

ccbsd2:precision/> gcc precdbl.c

ccbsd2:precision/> ./a.out

Before loop, x=1234567.200000

first y = 1234567.200100

After loop, x=1234568.000001

ccbsd2:precision/>

double 實數佔用 64 bits

交大資工 蔡文能 Sqrt-funBinary-55

再練習 array 與 Loop

• Magic square魔方陣• Diabolic square 鬼方陣• 奇數階魔方陣程式奇數階魔方陣程式• 偶偶數階魔方陣程式數階魔方陣程式 ??

• 四的倍數階四的倍數階魔方陣魔方陣

交大資工 蔡文能 Sqrt-funBinary-56

魔方陣與鬼方陣• Magic square

– 橫的直的斜的加起來都一樣的方陣– 所有的數字必須是連號– 三階魔方陣 :– 如何排 ? 2 9 4

7 5 3

6 1 8

交大資工 蔡文能 Sqrt-funBinary-57

當瑛姑遇上黃蓉 (1/5)• 三階魔方陣 (magic square)

九子斜排 , 四維挺出上下互易 , 左右相更

1 2 4 3 5 7 6 8 9

2 9 4

7 5 3

6 1 8

射鵰英雄傳

結果如下

交大資工 蔡文能 Sqrt-funBinary-58

當瑛姑遇上黃蓉 (2/5)• 三階魔方陣 (magic square)

九子斜排 , 四維挺出上下互易 , 左右相更

2 1 4 2 4 3 5 7 6 8 6 9 8

2 9 4

7 5 3

6 1 8

射鵰英雄傳

交大資工 蔡文能 Sqrt-funBinary-59

當瑛姑遇上黃蓉 (3/5)• 三階魔方陣 (magic square)

九子斜排 , 四維挺出上下互易 , 左右相更

2 9 4

3 5 7

6 1 8

2 9 4

7 5 3

6 1 8

射鵰英雄傳

交大資工 蔡文能 Sqrt-funBinary-60

當瑛姑遇上黃蓉 (4/5)• 三階魔方陣 (magic square)

九子斜排 , 四維挺出上下互易 , 左右相更

2 9 4

7 5 3

6 1 8

2 9 4

7 5 3

6 1 8

射鵰英雄傳

二四為肩六八為足左七右三戴九履一

交大資工 蔡文能 Sqrt-funBinary-61

當瑛姑遇上黃蓉 (5/5)• 三階魔方陣 (magic square)

九子斜排 , 四維挺出上下互易 , 左右相更

2 9 4

7 5 3

6 1 8

8 1 6

3 5 7

4 9 2

2 9 4

7 5 3

6 1 8

射鵰英雄傳

三階魔方陣只

有一解 ,右邊兩解相同轉 180度

交大資工 蔡文能 Sqrt-funBinary-62

Magic Square 魔方陣 (奇數階 )•Place 1 in the middle of the top row•after integer k has been placed, move up one row and one column to the right to place the next integer k+1, unless:

– If a move takes you above the top row in the j-th column, move to the bottom of the j-th column and place the integer k+1 there

– If a move takes you outside to the right of the square in the i-th row, place k+1 in the i-th row at the left side

– If a move takes you to an already filled square or if you move out of the square at the upper right-hand corner, place k+1 immediately below k.

交大資工 蔡文能 Sqrt-funBinary-63

Magic Square 魔方陣int x[19][19]; col

row

17 24 1 8 15

23 5 7 14 16

4 6 13 20 22

10 12 19 21 3

11 18 25 2 9

Wrap around

交大資工 蔡文能 Sqrt-funBinary-64

魔方陣魔方陣 ((奇數階奇數階 )) 程式程式• 前面講過的方法如何寫成程式 ?

– 何謂跑過上方要由下方走出來 ? (wrap around)– 何謂跑出右邊要由左方捲出來 ?– 要如何判斷往右上時該格子是否已經填過 ?– 真的需要判斷往右上時是否已經填過嗎 ?

能不能有別的方法 ? 換個角度想 ? 結果變成可用兩層的 Loop 完成

• 前面講過的方法如何寫成程式 ?– 何謂跑過上方要由下方走出來 ? (wrap around)– 何謂跑出右邊要由左方捲出來 ?– 要如何判斷往右上時該格子是否已經填過 ?– 真的需要判斷往右上時是否已經填過嗎 ?

能不能有別的方法 ? 換個角度想 ? 結果變成可用兩層的 Loop 完成

交大資工 蔡文能 Sqrt-funBinary-65

Magic Square 魔方陣• 先令 hand=0, 一開始站在 the middl

e of the top row 之正上方 ( 第 -1列 )• Loop 以下工作 n 次

– 往正下方走一格並將 hand 加 1 後填入

– Loop 以下工作 n-1 次 • 往右上角走一格並將 hand 加 1 後填入 (注意 Wrap around 捲回來 )

Algorithm Pseudo code 假碼

交大資工 蔡文能 Sqrt-funBinary-66

Magic Square 魔方陣 (cont)hand=0; row = -1; col = (n-1)/2; /* 在 0 列上方 *

/for( i = 1; i<=n; i++) {

row++; if(row>=n) row=0; /*往正下方一步 */hand++; x[row][col] = hand;for(j=1; j <= n-1; j++) { /*往右上角 n-1 步 */

row--; if(row<0) row=n-1; /*上移一列 */col++; if(col>=n) col=0; /* 右移一格 */hand++; x[row][col] = hand;

}; }

交大資工 蔡文能 Sqrt-funBinary-67

Magic Square 魔方陣 (cont 2)// …

// … 印出該方陣 , 一列一列地印出for( row = 0; row<= n-1; row++) {

for(col=0; col<= n-1; col++) {

printf(" %4d" , x[row][col] )

};

printf("\n"); /*每印完一列印出 new line */

}

交大資工 蔡文能 Sqrt-funBinary-68

問題與思考

Magic square 與 Pascal Triangle在使用 Loop 上有何異同 ?

交大資工 蔡文能 Sqrt-funBinary-69

p7.c 巴斯卡三角形 for(i=0; i<=n; i++) { x[i][0]=1; x[i][i] =1; /* 記得宣告 / 定義 x 陣列

喔 */

for(j=1; j<= i-1; j++) { x[i][j]= x[i-1][j] + x[i-1][j-1]; } for(j =0; j<=i; j++){ 1

printf("%5d", x[i][j]); 1 1 }; printf("\n"); 1 2 1 }; /* for i */ 1 3 3 1 1 4 6 4 1

i

第 j 格

交大資工 蔡文能 Sqrt-funBinary-70

Magic Square 魔方陣 (cont)hand=0; row = -1; col = (n-1)/2; /* 在 0 列上方 *

/for( i = 1; i<=n; i++) {

row++; if(row>=n) row=0; /*往正下方一步 */hand++; x[row][col] = hand;for(j=1; j <= n-1; j++) { /*往右上角 n-1 步 */

row--; if(row<0) row=n-1; /*上移一列 */col++; if(col>=n) col=0; /* 右移一格 */hand++; x[row][col] = hand;

}; }

交大資工 蔡文能 Sqrt-funBinary-71

More Magic Squares

Order = 4 ?

Order = 4 k, where k = 1, 2, 3, …

Order = 2 k, where k = 2, 3, …

交大資工 蔡文能 Sqrt-funBinary-72

偶數階魔方陣• 前面所說方法只適用在奇數階 , 偶數階呢 ?

• 二階魔方陣不存在• 三階魔方陣只有一個解 ( 旋轉 ..算一個 )

• 四的倍數階方陣有一個簡單解法• 四階魔方陣共有 880 個解• 二以外的偶數階方陣也有解法

交大資工 蔡文能 Sqrt-funBinary-73

四階Magic Square 魔方陣Order=4

16 2 3 13

5 11 10 8

9 7 6 12

4 14 15 1

四階魔方陣共有 880個

橫的 , 直的 , 斜的加起來都是34當

瑛姑遇上黃蓉

交大資工 蔡文能 Sqrt-funBinary-74

四階 Diabolical Square 鬼方陣Order=4

1 12 13 8

14 7 2 11

4 9 16 5

15 6 3 10

捲動一列或捲動一直行仍為魔方陣

橫的 , 直的 , 斜的加起來都是34

交大資工 蔡文能 Sqrt-funBinary-75

四階 Diabolic Square 鬼方陣Order=4

12 13 8

7 2 11

9 16 5

6 3 10

捲動一列或捲動一直行仍為魔方陣

橫的 , 直的 , 斜的加起來都是34

1

14

4

15

交大資工 蔡文能 Sqrt-funBinary-76

四階 Diabolic Square 鬼方陣Order=4

14 7 2 11

4 9 16 5

15 6 3 10

捲動一列或捲動一直行仍為魔方陣

橫的 , 直的 , 斜的加起來都是34

1 12 13 8

交大資工 蔡文能 Sqrt-funBinary-77

四階Magic Square 製作方法Order=4

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

橫的 , 直的 , 斜的加起來都是34當

瑛姑遇上黃蓉

由左而右依序填入 1 到 16

對角線經過處取 17補數

交大資工 蔡文能 Sqrt-funBinary-78

四階Magic Square 製作方法Order=4

16 2 3 13

5 11 10 8

9 7 6 12

4 14 15 1

四階魔方陣共有 880個

橫的 , 直的 , 斜的加起來都是34當

瑛姑遇上黃蓉

1+16=17

對角線經過處取 17補數

交大資工 蔡文能 Sqrt-funBinary-79

八階Magic Square 魔方陣Order=8 1 2 3 4

9 10 11 12

17 18

5 6 7 813 14 15 16

57 58 59 60

61 62 63 64

1+64=65

對角線經過處取65補數

由左而右由上而下填入1到64

交大資工 蔡文能 Sqrt-funBinary-80

八階Magic Square 魔方陣Order=8 64 2 3 61

9 55 54 12

17 20

60 6 7 57

13 51 50 16

?

15 14

8 58 59 5

? 18

11 10

4 62 63 1

1+64=65

對角線經過處取65補數 0 1 2 3 4 5 6 7

0

1

2

3

4

5

6

7

交大資工 蔡文能 Sqrt-funBinary-81

四的倍數階Magic Square 魔方陣int x[19][19]; /* 由左而右 , 由上而下填入 1到 n*n */

val=0; haha = 1+n*n;

for( i = 0; i<= n-1; i++) {

for(col=0; col<=n-1; col++){

val++;

if( isondiag( i, col) ) x[i][col]= val;

else x[i][col] = (1+n*n) – val ;

}

} 換成 haha

交大資工 蔡文能 Sqrt-funBinary-82

四的倍數階Magic Square 魔方陣 /* X[i][j] 是否在對角線上 ?

when index = 0, 1, 2, 3, 4, 5, 6, 7, …*/

int isondiag(int i, int j) {

i = i%4; j=j%4;

if(i == j ) return 1;

if( i+j == 3) return 1;

return 0; /* 0 means false */

}

交大資工 蔡文能 Sqrt-funBinary-83

四的倍數階Magic Square 魔方陣 //X[i][j] 是否在對角線上 ?

// when index = 1, 2, 3, 4, 5, 6, 7, 8, …

int isondiag(int i, int j) {

//?

//?

//?

return 0; /* 0 means false */

}

交大資工 蔡文能 Sqrt-funBinary-84

八階Magic Square 魔方陣Order=8 64 2 3 61

9 55 54 12

17 20

60 6 7 57

13 51 50 16

?

15 14

8 58 59 5

? 18

11 10

4 62 63 1

1+64=65

對角線經過處取65補數 1 2 3 4 5 6 7 8

1

2

3

4

5

6

7

8

交大資工 蔡文能 Sqrt-funBinary-85

四的倍數階Magic Square 魔方陣 /* X[i][j] 是否在對角線上 ?

when index = 1, 2, 3, 4, 5, 6, 7, 8, …*/

int isondiag(int i, int j) {

i = (i-1)%4; j=(j-1)%4;

if(i == j ) return 1;

if( i+j == 3) return 1;

return 0; /* 0 means false */

}

交大資工 蔡文能 Sqrt-funBinary-86

四的倍數階Magic Square 魔方陣 //判斷 x[i][j] 是否在對角線上 ?

// when index = 1, 2, 3, 4, 5, 6, 7, 8, …

bool isondiag(int i, int j) {

i = (i-1)%4; j=(j-1)%4;

if(i == j ) return true;

if( i+j == 3) return true;

else return false; /* else 可去掉 */

} //新版 C++才認識 bool

交大資工 蔡文能 Sqrt-funBinary-87

再談函數 ( 函式 ) function• 函數 – 你給它一些參數 , 它回傳給你一個值• 遞迴函數 (Recursive function) – 直接或間接叫自己• 參數 (parameter) = 讓函數參考的資料

– 給人家參考的叫 argument 引數– 函數的頭部括號內叫 parameter 參數– Argument 又叫做 actual parameter ( 實際參數 )– Parameter 通常指 formal parameter ( 形式參數 )

• 範例 :– ans = myfun(x, y); /* x, y are actual parameter */– double myfun(int m, float p2) { /*…*/ } /* m 與 p2 是 形

式參數或叫做虛擬參數 , formal parameter, 是別人傳過來的 */

交大資工 蔡文能 Sqrt-funBinary-88

常見 Recursive 問題• Factorial N : 求 N 階乘

– 能求到多大 ? 寫一程式印出 1 階乘到 52 階乘

• GCD(m, n)

• Quick Sort

• Fibonacci Rabbits problem

• Hanoi Tower

交大資工 蔡文能 Sqrt-funBinary-89

N Factorial ( N階乘 , N! )long factorial(int n) { long k, ans = 1; for(k=1; k<=n; ++k) ans = ans * k; return ans;} /*給我 n 我就告訴你 n 階乘 */#include <stdio.h>int main( ){ printf("5! = %ld\n", factorial(5));} N階乘就是 1*2*… *(N-1)*N

交大資工 蔡文能 Sqrt-funBinary-90

N Factorial ( Recursive 版 )

long factorial(int n) { if( n < 0) return - factorial(-n); if( n ==1 || n==0) return 1; return n * factorial(n-1);} /* 告訴我 n-1 階乘 , 我就給你 n 階乘 */#include <stdio.h>int main( ){ printf("5! = %ld\n", factorial(5));} N階乘就是 N 乘以 N-1階乘

交大資工 蔡文能 Sqrt-funBinary-91

歐幾里得的最大公約數• 輾轉相除法 (recursive概念 !)

GCD(m, n) = GCD(n, m%n)

但如果 n 是 0 則答案為 m

long gcd(long m, long n) {

if(n==0) return m;

return gcd(n, m%n);

} 如何寫成 non-recursive version ?

交大資工 蔡文能 Sqrt-funBinary-92

最大公約數 non-recursive版long gcd(long m, long n) { int r; /* remainder */ while(n != 0) { r = m%n; m = n; n = r; } return m;}

交大資工 蔡文能 Sqrt-funBinary-93

Recursive 也可以很有趣 (1/3)

Fibonacci Series: (費氏數列 )一開始有一對兔子 小兔子隔一個月可以長大為成兔 每對成兔每隔一個月可生出一對兔子 假設兔子永遠不死 , 問第 n 個月時有幾對兔子 ?

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, . fib(n)0 1 2 3 4 5 6 7 8 9 10 11 = n

交大資工 蔡文能 Sqrt-funBinary-94

Recursive 也可以很有趣 (2/3)

long fib(int n) { if( n < 0) return 0; if( n ==1 || n==0) return 1; return fib(n-1)+fib(n-2);} /* 給我 n 我就告訴你第 n 個月時有幾對兔子 */ /* 第 n 個月兔子數 = 第 n-1 個月兔子 + 第 n-2 個月兔子 */

/* 但是 , 最開始兩個月例外 ! */

交大資工 蔡文能 Sqrt-funBinary-95

Recursive 也可以很有趣 (3/3)

Fibonacci Series(費氏數列 ):1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …

34/55 = 55/89 = 89/144 = 0.618 黃金分割比 :)

神奇的費氏數列 : 任何事物接近這些數字會有變化

請看 . . 可怕的 巧合 : !? 三 重 魔 力 . . .

民國 34 年台灣光復 , 民國 89年變天 國民黨從日本手上搶回台灣執政剛好 55 年 !

交大資工 蔡文能 Sqrt-funBinary-96

Programming Concept Summary (1/3)

• 為了方便 , 一些宣告被寫在 header檔案 (標題檔案 ),要用 #include <filename.h> 把它抄進來

• 變數 (variable)就是佔住記憶體一小塊地方且有個名字• 變數名字要用字母開頭• 變數的種類 (類型 ):

– 整數 : char, (byte), short, int, long, long long (C99才有 )– 實數 : float, double, long double

• float 的準確度只有二進位 24 位 , 約十進位 7 位強• double 的準確度只有二進位 53 位 , 約十進位 15 位強• 每個 C 程式都要有一個主程式 int main( ) { /*…*/ }• /* 註解是給人看的 */ // C++ 是用兩斜線開始註解

交大資工 蔡文能 Sqrt-funBinary-97

Programming Concept Summary (2/3)

• 為了方便 , 用 array( 陣列 ) 來表示一大堆同性質變數• 若寫的每一句 (statement; 指述 ) 都只做一次 , 程式再大

也是一下子就執行完了 ! Control statements• Control Statements (控制指述 ):

– Sequential statement (循序 ) --- 就是沒控制– Selection (Alternative) 選擇 --- if (expression) stat-1; else stat-2;– Repetition (Loop)

• while loop• for loop• do while loop (repeat until in Pascal)

– Function call/return ; Recursive function : 直接或間接叫自己• 程式庫 (Library function) --- 方便程式員

交大資工 蔡文能 Sqrt-funBinary-98

Programming Concept Summary (3/3)

#include <stdio.h> /* C 的標題檔 */

#include <iostream> // C++ 的標題檔double myvar, var2[9]; //Global variable 全域變數int main ( ) {

float delta; // Local variable 區域變數 // assignment, control statements, …

// expression, function calls, …

}

交大資工 蔡文能 Sqrt-funBinary-99

Auto 變數佔用 STACK區memory

•Auto 變數就是沒寫 static 的 Local 變數

CPUIP

SP

Instruction Pointer

Stack Pointer

系統區

系統區

程式 +靜態 data

HEAP堆積STACK

012...

98769875...

交大資工 蔡文能 Sqrt-funBinary-100

再談 C Language 程式庫

• 程式庫裡除了 sqrt (double); 之外 , 還有許多常用的函數 ( 函式 ), 有許多其實都很簡單

• printf, scanf, getchar, fopen, … 這些與 I/O 有關的函數被宣告在 stdio.h, 所以要在程式中

#include<stdio.h>用 < > 夾起來表示在系統某個目錄之下 , 例

如 /usr/include/• 所有 Library function 參看 K&R 附錄 B

交大資工 蔡文能 Sqrt-funBinary-101

C 程式庫裡面的 toupper( )

int toupper( int x ) {

if(x>= 'a' && x <= 'z' ) x = x - 'a' + 'A';

return x;

}

注意 char 也是一種 int

交大資工 蔡文能 Sqrt-funBinary-102

C 程式庫裡面的 toupper( ) 新

int toupper( int x ) { return (x>= 'a' && x <= 'z' ) ? x - 'a' + 'A' : x;

}

? : 是 C裡面唯一的一個 trinary operator 三元運算子

其它都是 binary operator 或是 unary operator

Operator : 運算符號、 運算子 operand : 運算元(素 )

交大資工 蔡文能 Sqrt-funBinary-103

Trinary operator ( 三元運算子 )

ans = - b; /* unary operator */

ans = a + b; /* binary operator */

ans = a > b ? a : b;

? : 是 C裡面唯一的一個 trinary operator 三元運算子

其它都是 binary operator 或是 unary operator

Operator : 運算符號、 運算子 operand : 運算元(素 )

if (a > b) ans = a; else ans = b;

交大資工 蔡文能 Sqrt-funBinary-104

C 程式庫裡面的 islower( )

int islower( int x ) { if (x>= 'a' && x <= 'z' ) return 1;

return 0 ; /* 不需寫 else , why ? */

}

交大資工 蔡文能 Sqrt-funBinary-105

C 程式庫裡面的 islower( ) 新

int islower( int x ) { return (x>= 'a' && x <= 'z' ) ? 1 : 0 ;

}

Operator : 運算符號、 運算子 operand : 運算元(素 )

此例用到 C裡面唯一的一個 trinary operator

交大資工 蔡文能 Sqrt-funBinary-106

Other C Library functions

• strlen• strcpy, strcat• strncpy• … 字串相關處理函數 ( 函式 )• 很多 str 開頭的 Library functions 很有

用 , 要記得 #include <string.h>• 少數 str 開頭不是 #include <string.h> 如 strtod(char *) 和 strtol(char*)

交大資工 蔡文能 Sqrt-funBinary-107

計算 C 字串的長度 (1/2)

• 記憶體任何地方都可以是字串起點• 字串以一個 null byte ( 每個 bit 都是 0) 結束– 稱為 Null-terminated string– 有些語言是在字串開始記錄其長度 :Pascal

• 當字串一開始就是 null byte則長度為 0• Array 傳入函數是只傳 array 最開始元素

之 address; 假設 x 是個 array,– 則 myfun(x); 相當於 myfun( &x[0] );

交大資工 蔡文能 Sqrt-funBinary-108

計算 C 字串的長度 (2/2)

• 函數如何接受傳過來的 array ?– 記住傳過來的是 array 第 0 元素的 address

– 所以要用 pointer 來接• Pointer 與 array 用起來互通

– x[0] 與 *x 是完全一樣的– x[3] 與 *(x+3) 是完全一樣的– x[k] 與 *(x+k) 是完全一樣的

• 傳入的字串其實是字串開始的位址 (address)

交大資工 蔡文能 Sqrt-funBinary-109

Library function strlen (1/3)

int strlen(char * p) /* 同 (char p[ ]) */{ int ans=0; while(p[ans]) ++ans; return ans;}

#include <stdio.h>int main( ) { printf(" 字串長為%d\n", strlen("abcde") );} 答案是 5

指標可以當 array 用

交大資工 蔡文能 Sqrt-funBinary-110

strlen (2/3)

int strlen(char * p) /* 同 (char p[ ]) */

{ int ans= -1;

while(p[++ans]) ;

return ans;

}

k = strlen("abcde");指標可以當 array 用

交大資工 蔡文能 Sqrt-funBinary-111

strlen (3/3)

int strlen(char * p) /* 同 (char p[ ]) */

{ char * pold = p;

while(*p) ++p;

return p - pold;

}

k = strlen("abcde");

pold

交大資工 蔡文能 Sqrt-funBinary-112

strcpy 字串考貝char* strcpy(char * dest, char* src) { char * olddest = dest; while(*src) { /* not NULL */ *dest = *src; /*注意 *src 與 src[0] 同 */ ++dest; ++src; } dest[0] = 0; /* NULL 也要 copy 進去 */ return olddest;}

strcpy 是危險的 function! 因不知 dest 是否夠位置

NULL 就是 0

Strncpy 最多 copy n 個 bytes怎麼寫 ?

交大資工 蔡文能 Sqrt-funBinary-113

strcat 字串接起來char* strcat(char * dest, char* src) { char *pold = dest; while(*dest) ++dest; /* until the tail of the string*/ while(*src) { /* not NULL */ *dest = *src; /*注意 *src 與 src[0] 同 */ ++dest; ++src; } *dest = 0; /* NULL 也要 copy 進去 */ return pold;}

strcat 也是危險的 function! 因不知 dest 是否夠位置

NULL 就是 0

concatition 接起來

交大資工 蔡文能 Sqrt-funBinary-114

Standard C Library<stdio.h> <math.h> <stdlib.h><string.h> <ctype.h> <time.h><assert.h> <float.h> <limits.h><stdarg.h> <stddef.h> <errno.h><locale.h> <signal.h> <setjmp.h>• open, read, write, close 等不是 standard C Lib

rary, 而是 system call• C Library 在 UNIX 手冊第三章 , System call

在 UNIX 手冊 第二章 ( 用 man 會看到 (2) )• 所有 Library function 參看 K&R 附錄 B

交大資工 蔡文能 Sqrt-funBinary-115

<algorithm> <bitset> <complex> <deque>

<exception> <fstream> <functional> <iomanip>

<ios> <iosfwd> <iostream> <istream>

<iterator> <list> <locate> <limits>

<map> <memory> <new> <numeric>

<ostream> <queue> <streambuf> <string>

<set> <sstream> <stack> <stdexcept> <typeinfo> <utility> <valarray> <vector>

<cmath>

C ++ class Library

交大資工 蔡文能 Sqrt-funBinary-116

Thank You!Thank You!

謝謝捧場[email protected]

蔡文能