c 語言中的變數型態
DESCRIPTION
大數. C 語言中的變數型態. 資料來源: 2008 寒訓講義. 若要存 ” 擁有超過 19 位有效位數的 ” 數字?. “ 使用 array” 的概念. 把一個 n 位數的數字當作(分解成)好幾個 k 位數。 運算過程的 overflow---- 估計位數 arr[0] 要放最低位數 or 最高位數 ? arr[0] 放最高位數時,若有進位,現有位數都要往後移一格(也可預先留)。運算時,要先知道開始運算的位數(最低位)放在哪一格。要全部後移時,可用 memmove(&a[0],&b[0],sizeofbytes) 。. Input 不超過 100 位數 - PowerPoint PPT PresentationTRANSCRIPT
大數
C 語言中的變數型態型態名稱 所需記憶體 數值範圍
bool 1 bit 0,1 (即 true 跟 false)
char 1 byte -128 ~ 127 (ASCII Code)
int 4 byte -231~231-1 (約 10 位整數 )-2,147,483,648~2,147,483,647
unsigned int 4 byte 0~232-1 (約 10 位整數 )0~4,294,967,295
long 4 byte -231~231-1 (約 10 位整數 )-2,147,483,648~2,147,483,647
unsigned long 4 byte 0~232-1 (約 10 位整數 )0~4,294,967,295
long long 8 byte -263~263-1 (約 19 位整數 )-9,223,372,036,854,775,808~9,223,372,036,854,775,807
float 4 byte ±3.4×10-38 ~ ±3.4×1038 ( 有效位數 7位 )
double 8 byte ±1.7×10-308 ~ ±1.7×10308 ( 有效位數 15位 )
long double 8 byte ±1.7×10-308 ~ ±1.7×10308 ( 有效位數 15位 )
資料來源: 2008 寒訓講義
• 若要存”擁有超過 19 位有效位數的”數字?
“使用 array” 的概念 把一個 n 位數的數字當作(分解成)好幾個 k 位數。
運算過程的 overflow---- 估計位數 arr[0] 要放最低位數 or 最高位數 ? arr[0] 放最高位數時,若有進位,現有位數
都要往後移一格(也可預先留)。運算時,要先知道開始運算的位數(最低位)放在哪一格。要全部後移時,可用memmove(&a[0],&b[0],sizeofbytes) 。
Input 不超過 100 位數567890123456789012345678995678901234567890123456789Output101357802469135780246913578
char array
1. inputASCII 轉換成整數型態
2. 開始運算3. 整數轉換成 ASCII 型態4. output
codetemp424.c
Input與 ASCII整數
資料型態 char : ASCII 的世界也是整數的世界
%d 0 … 10 48 49 … 57 65 66 … 90 97 98 …122
%c ‘\0’ … ‘\n’ ‘0’ ‘1’… ‘9’ ‘a’ ‘b’… ‘z’ ‘A’ ‘B’…’Z’
平常處理 char我們都用%c,也是看到我們熟悉的字元,但實際儲存在 char裡的資料卻是用整數的字元 ASCII碼。
上面兩組 code都會印出 10 空白 與換行。
char temp=’\n’;
printf(“%d %c”,temp,temp);
上面的 code當然也是一樣。
所以 code裡的-‘0’ -48是做甚麼用的?
‘0’ (48) >> 0
‘1’ (49) >> 1
… …
‘9’ (57) >> 9
正解:把 char裡的儲存的 整數 ASCII碼 變成 整數。
臨時忘記可以用 printf("%d %d %d %d %d %d %d %d",'\0','\n','0','9','a','z','A','Z');
char temp;
temp=10;
printf(“%d %c”,temp,temp);
int ten=10;
char temp;
temp=ten;
printf(%d %c“,temp,temp);
下一頁
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 進位。
一格存一位數arr1[4] arr1[3] arr1[2] arr1[1] arr1[0]
4 5
arr2[4] arr2[3] arr2[2] arr2[1] arr2[0]
5 6
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
11
carry
1
11001
Input3 2
967
34
Output1001
codetemp10013.c
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)
直式減法c0=a0-b0-carry0if(c0<0){
c0=c0+ncarry1=1
}else{
carry1=0}
1 0 0 5
9 9 9
-100-100
-1
那 999-1005?
1 0 0 5
9 9 9
0 0 0 6
答案是 -6另外宣告 char arr3sign=‘-’;
arr2[]
arr1[]
arr3[]
-46
-1-1
0
if(a0>=b0+carry0){c0=a0-b0-carry0carry1=0;
}else{
c0=n+a0-b0-carry0carry1=1
}
c0=a0-b0-carry0if(c0<0){
c0=c0+ncarry1=1
}else{
carry1=0}
因為程設課本說有些硬體不允許在 char 裡面存負數
負數出現現在把加減法都考慮負數:大 >0 ,小 >0, |大 |>|小 |+ 大 – (+小 ) = ++ 大 – (-小 ) = +- 大 – (+小 ) = -- 大 – (-小 ) = -+ 小 – (+大 ) = -+ 小 – (-大 ) = +- 小 – (+大 ) = -- 小 – (-大 ) = +
減法就有 8 種可能性 !
• 先看加法(把加法的程式擴充)數字部分用加法,再補正負號。
else
數字部分用減法,再補正負號。
arr2-arr1 ,補正負號(與大數同號)。
正 +正負 +負正 + 負負 + 正
+ 大 +(-小 )
- 大 + (+小 )+小 +(-
大 )
-小 + (+大 )
• 再看減法(把減法的程式擴充或利用 a+(-b) 附屬在加法)
數字部分用加法,再補正負號。else
數字部分用減法,再補正負號。
arr2-arr1 ,補正負號(與大數同號)。
負 - 正正 - 負
正 - 正負 - 負
+ 大 -(+小 )
- 大 - (-小 )+ 小 -(+
大 )
- 小 - (-大 )
出現負數與減法後該注意的不論加減法,運算完後會因為連續退位出現很多 leading 0 ,至少在 output 之前要記得調整長度。
調整長度時 長度是 1 。0 0 0 0
乘法• product00=(a00*b00+carry00)mod n• carry01= (a00*b00+carry00) / n
• sum0=product00• sum1=product01+product11
125* 25-------------------------- 625 250+)------------------------ 3125
乘法arr1[4] arr1[3] arr1[2] arr1[1] arr1[0]
9 9 9
arr2[4] arr2[3] arr2[2] arr2[1] arr2[0]
9 9
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
81
carry
8
189
999* 99-------------------------- 8991 8991+)------------------------ 98901
98998
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
8190
9
081909819089 19998
在這個模擬中,加法被隱含在乘法中
product11+product01product12+carry12 +product02
arr3len++;
乘法被乘數有 a 位數乘數有 b 位數積最多有 a+b 位數(有人有問題嗎?):1 考慮運算過程的 overflow ,能存 n 位數的資料
型態,我們最多只存 n/2 位數2 準備好足夠的格子才放得下積做幾次加法是由乘數的格數決定
將加法包成函式現在就能再利用了特殊情況!:只要乘數為零,積為零且長度為 1 。
結構• arr[]*3 存數字:被乘數、乘數、積• position*3 存最高位位置(低位已知,可不
存)• carry 暫存進位
一格存 K 位數
一格存 K 位數arr1[4] arr1[3] arr1[2] arr1[1] arr1[0]
2 45
arr2[4] arr2[3] arr2[2] arr2[1] arr2[0]
7 56
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
101
carry
1
110
11245
+ 756-------------------------- 1001
乘法arr1[4] arr1[3] arr1[2] arr1[1] arr1[0]
99 99 99
arr2[4] arr2[3] arr2[2] arr2[1] arr2[0]
99 99
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
9801
carry
98
19899
999999* 9999-------------------------- 98999901 98999901+)------------------------ 9998990001
9998999998
arr3[4] arr3[3] arr3[2] arr3[1] arr3[0]
98019900
99
09801990099980199009899 199999998
在這個模擬中,加法被隱含在乘法中
product11+product01product12+carry12 +product02
arr3len++;
一格存 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比 char array 好。 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