位元組數
char 1
short 2
int 由平台(編譯器)決定,可能是2或4,通過sizeof獲知
long 由平台(編譯器)決定,可能是4或8
float 4
double 8
char*/float* /… x86,4位元組,x64,8位元組
資料範圍
(signed)char (1位元組) -128——127
unsigned char 0——255
(signed) short (2位元組) -32768——32767
unsigned short 0——65535
(signed ) int (4位元組) -2147483648——2147483647
unsigned int 0——4294967295
(signed) long(8位元組) -9.223372036854776e+018——9.223372036854776e+018
注:9,223,372,036,854,775,808
unsigend long 0——1.844674407370955e+19
注:18,446,744,073,709,551,615
float -3.4e-38——3.4e+38
double -1.7e-308——1.7e+308
平台無關的整型型別
原因:由於在32位機器和64位機器中,long佔據不同的位元組數;不同編譯器下,int、long都可能占用不同位元組數;為了**的直觀
標頭檔案:stdint.h
int8_t
uint8_t
int16_t
uint16_t
int32_t
uint32_t
int64_t
uint64_t
標頭檔案:stddef.h
ssize_t和size_t分別是sign size_t和unsigned signed size of computerwordsize。它們也是表示計算機的字長,在32位機器上是4位元組,在64位機器上8位元組
浮點數精確至小數點後多少位
檢視float.h的巨集定義
#define flt_dig 6
/* # of decimal digits of precision */
#define dbl_dig 15
/* # of decimal digits of precision */
原理是根據浮點數的表示方法,尾數部分就是決定了浮點數的精度,對於float, log10(223) = 6.9237,所以是小數點後6位,對於double,log10(252)=15.6536,所以是小數點後15位
浮點數的整數範圍
ieee754 單精度和雙精度浮點數,能夠精確表示的整數的範圍為
single precision [-2^24, 224],等價於10進製的log10(224)=7.2數量級
double precision [-2^53, 253],等價於10進製的log10(224)=15.9數量級
原理參考
注:受限於浮點數的尾數字,其表示精度是有限的(有效數字),對於很小的小數、或者很大的整數,其精度都會不足。浮點數的精度不是平均分布的呢,和整數的均布不同,浮點數精度是「兩頭差,中間好」。
為什麼對於很小的小數或者很大的整數,會出現精度不足的問題?
這裡需要理解浮點數的表示方法以及浮點數的規範化。
浮點數會將實際的數值規範化為科學計數法的表示形式,如121.75,規範化後是1.2175e+2,當然,計算機裡要換成二進位制的:
(121.75)10 = (1111001.11)2
對二進位制數規範化,1111001.11小數點左移6位,然後乘上2的6次方
浮點數分為符號、指數和尾數三部分。
資料型別 符號位 指數字 尾數字
float 31 30~23 22~0
double 63 62~52 51~0
其中,float的指數字是偏移值,相對127偏移的值就是實際的指數值,如,129,指數值為129-127=2,表示2的2次方;同理,double也是偏移值,相對1023偏移。
尾數儲存規範化後的小數部分,規範化後的整數部分恒為1,所以不用特意分配乙個位元儲存這個1。
對於上面的例子,1111001.11在記憶體中的儲存形式如下(假設這是乙個float型別):
首先,符號位是0
接著,規範化後的值 1.11100111,小數部分共8位,需要補足至23位,最終的尾數字是11100111000000000000000
最後,規範化的指數值是6,表示為偏移值 127+6=133,轉換為二進位制10000101,最終的指數字是10000101
所以,1111001.11在記憶體中儲存為0, 10000101, 11100111000000000000000
回到問題本身,由於浮點數的尾數字有限,有效數字是有限的(float是24位,double是53位),如果實際數值的有效數字超過浮點數字數限制,超出的位將會丟失。
例如,11100111000000010001000.11(十進位制為7569544.75),其有效數字是25位,如果用float表示,即
float value = 7569544.75;
觀察value在記憶體中的值:
0,10010101,11001110000000100010010
0,011111001,0011001100110011001101
將尾數與原始數比較
11100111000000010001000.11
11001110000000100010010
可以發現,尾數部分剛好是原始數小數點左移22位後將高位"1"省略,並且原始數的小數點後第2位被丟棄了,丟棄的同時進行了捨入,如下所示:
……100011 最後一位捨入變成 ……10010
所以最終的value是等於7569544.0的,此時精確到小數點後1位(這裡為0是因為剛才捨入進一了),這種情況就是所謂的「很大的整數」,整數部分的有效數字較多,導致較低位被丟棄。而所謂的「很小的小數」就是指那些無限小數,如0.2,這些無法用二進位制精確表示的小數(因為二進位制是不斷用0.5+0.25+0.125……來逼近原始數的),由於存在尾數捨棄,就會產生精度問題,「很小的小數」就是那些很小的小數字
為什麼float能夠表示的範圍是[-3.4e-38,3.4e+38],而精確表示的範圍是[-2^24, 2^24]?
前者指的是float能夠表示的最大(最小)整數,但是最大整數與第二最大整數之間的差並不是1,也就是說這兩個數之間還存在很多整數float無法表示。
而後者指的就是,在[-2^24, 224]內,最大整數與第二最大整數間的差就是1,即224=16777216,float能夠表示,2^24-1=16777215,float也能夠顯示。
而對於[-3.4e-38,3.4e+38],這裡精確值就不計算了,假設最大值就是 34……56(共39位十進位制數),float能夠表示,但是34……55,float就不能表示了。
原理跟上面乙個問題的是一樣的,都是因為浮點數的尾數字有限,有效數字限制了所能表達的整數值,一旦有效數字大於24,多出來的較低位數字就會被捨棄。
關於printf
注意,printf(或sprintf、scanf、sscanf)的格式化字串 %lf輸出double值,必須加上精確位數,否則預設輸出小數點後6位
資料型別相關
整型常量 十進位制 18 31 long int型常量 123l 123l 123456l 123456l unsigned int型常量 123u 123u 根據實際資料大小確定int型還是long型 l以數字 0 開始的整型常量是八進位制數 022 037 010和10大小不一樣 因為八進位制並...
OCI資料型別與C語言資料型別問題
通過oci函式執行資料庫sql,提取值到記憶體中進行處理,執行sql如下 select out bytes 1024 from bf discharge info t 使用函式ocidefinebypos進行繫結時,oci型別使用的sqlt int,導致資料被取整,應該使用sqlt flt。oci資...
C 資料型別長度問題
一 位元組和字長 位元組,八位就是乙個位元組,是固定概念。字長是指計算機一次能處理的二進位制資料的長度,是乙個非固定的概念。例如,8位計算機的字長為8,即乙個位元組,32位計算機的字長位32,即4個位元組,同理,64位計算機的字長為64,即8位元組。二 c 中的資料型別 1 字元型資料char,該型...