290 likes | 464 Views
大數. C 語言中的變數型態. 資料來源: 2008 寒訓講義. 若要存 ” 擁有超過 19 位有效位數的 ” 數字?. “ 使用 array” 的概念. 把一個 n 位數的數字當作(分解成)好幾個 k 位數。 運算過程的 overflow---- 估計位數 arr[0] 要放最低位數 or 最高位數 ? arr[0] 放最高位數時,若有進位,現有位數都要往後移一格(也可預先留)。運算時,要先知道開始運算的位數(最低位)放在哪一格。要全部後移時,可用 memmove(&a[0],&b[0],sizeofbytes) 。. Input 不超過 100 位數
E N D
C語言中的變數型態 資料來源:2008寒訓講義
“使用array”的概念 • 把一個n位數的數字當作(分解成)好幾個k位數。 • 運算過程的overflow----估計位數 • arr[0]要放最低位數or最高位數? • arr[0]放最高位數時,若有進位,現有位數都要往後移一格(也可預先留)。運算時,要先知道開始運算的位數(最低位)放在哪一格。要全部後移時,可用memmove(&a[0],&b[0],sizeofbytes)。
Input 不超過100位數 5678901234567890123456789 95678901234567890123456789 Output 101357802469135780246913578
char array 1. input ASCII轉換成整數型態 2. 開始運算 3. 整數轉換成ASCII型態 4. output
stdlib.h的int atoi(const char *nptr) int number; char nptr[]={‘3’,’4’,’5’,’6’,’\0’}; // nptr[]=“3456” number=atoi(nptr); number=3456; #include<stdlib.h>
直式加法 • sum0=(carry0+a0+b0)mod n • carry1= (carry0+a0+b0) / n • 一格存1位數的話,n就是10,因為是10進位。 • 一格存3位數的話,n就是1000,因為是1000進位。
一格存一位數 1 1 10 0 11 1
char array • 跟組合語言格式一樣 • +-*/與=都跟整數一樣 • 可用字串處理函式ch8、9(c),ch26(c++) • strlen (以’\0’標記結束位置)(‘\0’==整數0) • strcpy(arr1,arr1)(會出錯)、memmove • printf(“%s”,arr); (arr[0]放最高位) • 讀入字串 gets(arr)、scanf(“%s”,arr)
直式減法 -1 -1 -1 c0=a0-b0-carry0 if(c0<0){ c0=c0+n carry1=1 } else{ carry1=0 } 0 -10 0 -10 0 -4 6 那999-1005? arr2[] arr1[] arr3[] 答案是 -6 另外宣告char arr3sign=‘-’;
因為程設課本說有些硬體不允許在char裡面存負數因為程設課本說有些硬體不允許在char裡面存負數 c0=a0-b0-carry0 if(c0<0){ c0=c0+n carry1=1 } else{ carry1=0 } if(a0>=b0+carry0){ c0=a0-b0-carry0 carry1=0; } else{ c0=n+a0-b0-carry0 carry1=1 }
負數出現 現在把加減法都考慮負數: 大>0,小>0,|大|>|小| +大 –(+小)=+ +大 –(-小)=+ -大 –(+小)=- -大 –(-小)=- +小 –(+大)=- +小 –(-大)=+ -小 –(+大)=- -小 –(-大)=+ 減法就有8種可能性!
先看加法(把加法的程式擴充) 數字部分用加法,再補正負號。 else 數字部分用減法,再補正負號。 arr2-arr1,補正負號(與大數同號)。
再看減法(把減法的程式擴充或利用a+(-b)附屬在加法)再看減法(把減法的程式擴充或利用a+(-b)附屬在加法) 數字部分用加法,再補正負號。 else 數字部分用減法,再補正負號。 arr2-arr1,補正負號(與大數同號)。
出現負數與減法後該注意的 不論加減法,運算完後會因為連續退位出現很多leading 0,至少在output之前要記得調整長度。 調整長度時長度是1。
乘法 • product00=(a00*b00+carry00)mod n • carry01= (a00*b00+carry00) / n • sum0=product00 • sum1=product01+product11 125 * 25 -------------------------- 625 250 +)------------------------ 3125
乘法 8 9 8 89 9 89 9 81 1 9 90 81 98 8 99 81 90 9 0 90 81 1 999 * 99 -------------------------- 8991 8991 +)------------------------ 98901 arr3len++; product11+product01 product12+carry12 +product02 在這個模擬中,加法被隱含在乘法中
乘法 被乘數有a位數 乘數有b位數 積最多有a+b位數(有人有問題嗎?): 1考慮運算過程的overflow,能存n位數的資料型態,我們最多只存n/2位數 2準備好足夠的格子才放得下積 做幾次加法是由乘數的格數決定 將加法包成函式現在就能再利用了 特殊情況!:只要乘數為零,積為零且長度為1。
結構 • arr[]*3存數字:被乘數、乘數、積 • position*3存最高位位置(低位已知,可不存) • carry暫存進位
一格存K位數 1 10 101 1 11 245 + 756 -------------------------- 1001
乘法 98 99 98 9899 99 99 9899 9801 1 99 9900 9801 9998 98 9999 9801 9900 99 0 9900 9801 1 999999 * 9999 -------------------------- 98999901 98999901 +)------------------------ 9998990001 arr3len++; product11+product01 product12+carry12 +product02 在這個模擬中,加法被隱含在乘法中
一格存K位數 • 以一格存4位數為例: • printf(“%04d”,arr[i]); • cout << cout.width(4) << fill(‘0’) << arr[i]; • 最高位數是不用補零的! • 通常讀入數字時需要轉換(讀入格式通常不會K位數剛好一格給你讀入),轉換可以用stdlib.h的int atoi(const char *nptr), • ex: char nptr[]=“3456” -> int number=3456
I/O • 從最高位數輸出 • 最高位數不補零(一格存K位數) • 零仍然要顯示一個‘0’(當然不補零) • 順應題目給的讀入格式讀入,再轉換成自己想用的儲存方式。
? • sprintf(輸出數字仍要以格為單位需用迴圈)、sscanf並不能用到%s的特性 • 依題目需求(空間限制、時間限制、要做乘法與否),會有不同的適用方法,若限制寬鬆,也可選擇比較容易(比較習慣)寫出code的方法。 • ex要節省空間時,一格存K位數的整數array比chararray好。 • ex:char (1 byte)加法可存2位;乘法存1位。 • int(4bytes)加法存9位沒問題;乘法存4位。 • long long int (8bytes)加法存18位沒問題;乘法存9位。 • 但是讀入數字時需要轉換,耗費轉換時間。
424 integer inquiry • 10013 super long sum//output最後要換行 • 10106 product • 485 pascal’s triangle of death • 495 fibonacci freeze