1 / 28

主題 : Big number ( 大數 )

主題 : Big number ( 大數 ). 解題技巧 什麼是大數? 大數運算 加法 減法 乘法 例題講解 : H.91.4 歷年題目. 什麼是大數?. 怎麼存下面的數字 100000 : int (-2 31 ~ 2 31 -1) 10000000000 : __int64 (-2 63 ~ 2 63 -1) 1000000000000000000000 : 怎麼存? 目前 C 只能用 64 bit 儲存整數, 64 bit 存不下的數字就稱為大數. 如何儲存大數. 正確評估 max_len

vevina
Download Presentation

主題 : Big number ( 大數 )

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 主題: Big number (大數) • 解題技巧 • 什麼是大數? • 大數運算 • 加法 • 減法 • 乘法 • 例題講解: H.91.4 • 歷年題目

  2. 什麼是大數? • 怎麼存下面的數字 • 100000 : int (-231 ~ 231-1) • 10000000000 : __int64 (-263 ~263-1) • 1000000000000000000000 : 怎麼存? • 目前 C 只能用 64 bit 儲存整數,64 bit 存不下的數字就稱為大數

  3. 如何儲存大數 • 正確評估 max_len • 最大數要多少位元 (10 進位),保證不會 overflow • 5 位數 + 4 位數 <= 6 位數 • 5 位數 × 4 位數 <= 9 位數 • 用 string 來儲存 • char x[max_len+1] • x = “684597315274” • 將每個位數用一個字元來儲存,運算時再轉換回數字

  4. 如何儲存大數 • 用整數陣列來儲存 (for 運算,較容易) • int num[max_len] = { 4, 7, 2, 5, 1, 3, 7, 9, 5, 4, 8, 6, 0, ..., 0} • 要記得補 0 • 不補 0 要記有效位元長度,速度快但程式不好寫 個位數 0 0 0 0 0 0 0 2 3 4 × 0 0 0 0 0 0 0 0 5 6

  5. 大數運算 • 大數運算 • 加法 • 乘法 • 減法

  6. 大數加法 • 原理 • 既然 C 程式內建的加法不能用,那就用最原始的加法 • 要注意進位的動作 1 1 4 1 7 8 + 4 2 5 4 6 0 3

  7. 資料結構 • int num1[max_len], num2[max_len] • 用來儲存數字 • int answer[max_len] • 用來儲存結果 • int carry

  8. 大數加法 • 123456789 + 987654321 ? • 把 123456789 存在 num1 之中,987654321 存在 num2,結果存在 answer 中 carry 1 1 1 1 1 1 1 1 1 0 num1 0 1 2 3 4 5 6 7 8 9 num2 + 0 9 8 7 6 5 4 3 2 1 answer 1 1 1 1 1 1 1 1 1 0

  9. C code void big_add( int *num1, int *num2, int *answer ){ int i; carry = 0; for ( i = 0 ; i < max_len ; i++) { answer[ i] = (num1[ i] + num2[ i] + carry) % 10; carry = (num1[ i] + num2[ i] + carry) / 10; } if (carry != 0) printf(“Overflow!!!\n”); }

  10. 大數乘法 • 原理 • 乘法其實就是很多個加法 • 注意進位和位數 4 1 7 8 × 4 2 5 4 2 0 3 2 0 8 9 0 1 0 1 8 3 5 6 3 1 0 3 1 6 7 1 2 1 0 0 0 1 1 1 7 7 5 6 5 0

  11. 資料結構 • num1, num2, carry 和加法一樣 • 中間的過程要用二維陣列來儲存? • 不用,和加法一樣只需要一個一維陣列 answer • 每次有新的值乘出來之後,就把它加到適當的位置去

  12. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 7 8 4 1 7 8 0 0 0 0 × 4 2 5 × 4 2 5 4 2 0 3 0 0 2 0 8 9 0 2 0 8 9 0 0 1 1 0 0 8 3 5 6 + 8 3 5 6 3 1 0 3 + 1 6 7 1 2 0 1 0 4 4 5 0 1 0 0 0 1 1 1 7 7 5 6 5 0 + 1 6 7 1 2 1 7 7 5 6 5 0

  13. C code void big_mul( int *num1, int *num2, int *answer ){ int i, j; for (i = 0; i < max_len) ; i++){ carry = 0; for (j = 0; j < max_len ; j++){ if (( i + j ) < max_len) answer[i+j] = (answer[i+j] + num1[j] * num2[i] + carry) % 10; carry= (answer[i+j] + num1[j] * num2[i] + carry) / 10; } } }

  14. 小技巧 • 在做大數運算時,可以將數個位數當成同一個位數來運算 • 之前的例子都是十進位,若換成百進位的話結果會如何? 4 1 7 8 × 4 2 5 10 19 1 0 4 4 5 0 3 1 1 6 7 1 2 1 7 7 5 6 5 0

  15. 當每一次運算所使用的位數增加時,總共所需要計算的次數就會減少,所要開的陣列大小也跟著變少當每一次運算所使用的位數增加時,總共所需要計算的次數就會減少,所要開的陣列大小也跟著變少 • 若陣列的型態為整數的話,則最多只能以萬進位為計算的單位 • 10000*10000 < 2^32

  16. 大數減法 • 原理 • 跟加法、乘法差不多 • 要注意借位 • 可以先判斷減數或被減數大,拿大的去減小的,最後再補正負號即可

  17. 大數減法 • 425 – 4178 = – (4178 – 425 ) = –3753 -1 4 1 7 8 – 4 2 5 3 7 5 3 –

  18. C code /* 假設 num1 比 num2 大 */ void big_sub( int * num1, int *num2, int *answer ){ int i; carry = 0; for (i = 0; i < max_len ; i++) { answer[ i] = num1[ i] – num2[ i] + carry; if (answer[ i] < 0) { answer[ i] = answer[ i] + 10; // 若是百進位則加100 carry = -1; } else carry = 0; } if (carry != 0) printf(“Underflow!!!\n”); }

  19. 例題講解: H.91.4http://www.cs.tku.edu.tw/info_race2002/codeq.htm • [a0, a1, …, an],其中每一個 ai 都是 0 到 9之間的整數,而且 n  50 (最多有 51 個數字) …

  20. Example • 將連分數轉成分數

  21. Sample input/output Sample input: 1,1,1,2 Sample 5 8 a0,a1,a2,a3 分子 分母

  22. 分析 = = = =

  23. 分析 • 所需的動作 • 乘法 • 加法 • 分子分母對調 • Easy?

  24. 分析 • 每個 ai 最大有可能到 9,最多可能有 51 個 9 連乘 • 9^51 >> 2^63 • 需要大數加法和大數乘法

  25. 需要的資料結構 • int num[51] • 儲存 a0到 an,最多有 51 個數 • int x[51] // 分子 • 9^51 位數最多只會有 51 位 • int y[51] // 分母

  26. Program structure intial_分子_分母(); for (i = n – 1; i >= 0; i++){ count_new分子_new分母(); }

  27. C code int x[51], y[51], newx[51], newy[51]; x[0] = 1; y[0] = an; for (i = n – 1; i >= 0; i++){ newx  y; newy  big_add ( big_mul ( y , ai) , x ) ; /* newy = y × ai + x; */ x  newx; y  newy; } 這裡的大數乘法是 一個大數乘以一個整數,較簡單

  28. 歷年題目 • 練習題 • A. 495 Fibonacci Freeze • http://acm.uva.es/p/v4/495.html • A. 623 500! • http://acm.uva.es/p/v6/623.html • A. 338 Long Multiplication • http://acm.uva.es/p/v3/338.html • A. 619 Numerically Speaking • http://acm.uva.es/p/v6/619.html • 挑戰題 • 2004兩岸清華學生程式比賽 Problem D • http://venus.cs.nthu.edu.tw/~jous/NTHU2004-Problems.doc • http://venus.cs.nthu.edu.tw/~jous/pd.exe • A. 288 Arithmetic Operation with Large Integers • http://acm.uva.es/p/v2/288.html • 其它歷年題目 • 無

More Related