C数据类型相关问题
2016-12-05 13:35
288 查看
字节数
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字节
浮点数的整数范围
IEEE754 单精度和双精度浮点数,能够精确表示的整数的范围为
Single precision [-2^24, 2^24],等价于10进制的log10(2^24)=7.2数量级
Double precision [-2^53, 2^53],等价于10进制的log10(2^24)=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表示,即
观察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, 2^24]内,最大整数与第二最大整数间的差就是1,即2^24=16777216,float能够表示,2^24-1=16777215,float也能够显示。
而对于[-3.4e-38,3.4e+38],这里精确值就不计算了,假设最大值就是 34……56(共39位十进制数),float能够表示,但是34……55,float就不能表示了。
原理跟上面一个问题的是一样的,都是因为浮点数的尾数位有限,有效数字限制了所能表达的整数值,一旦有效数字大于24,多出来的较低位数字就会被舍弃。
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字节
浮点数的整数范围
IEEE754 单精度和双精度浮点数,能够精确表示的整数的范围为
Single precision [-2^24, 2^24],等价于10进制的log10(2^24)=7.2数量级
Double precision [-2^53, 2^53],等价于10进制的log10(2^24)=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, 2^24]内,最大整数与第二最大整数间的差就是1,即2^24=16777216,float能够表示,2^24-1=16777215,float也能够显示。
而对于[-3.4e-38,3.4e+38],这里精确值就不计算了,假设最大值就是 34……56(共39位十进制数),float能够表示,但是34……55,float就不能表示了。
原理跟上面一个问题的是一样的,都是因为浮点数的尾数位有限,有效数字限制了所能表达的整数值,一旦有效数字大于24,多出来的较低位数字就会被舍弃。
相关文章推荐
- java基本数据类型相关问题
- java中基本数据类型的相关问题
- 关于JAVA中的基本数据类型的转换相关问题
- Oracle 日期数据类型的相关问题
- 关于数据类型取值范围相关问题
- java数据类型相关的问题
- C++ 数据类型及相关问题 及输出精度控制
- Spark 数据导入时的类型检测相关问题
- 数据类型相关问题
- java 基本数据类型的转换相关问题
- String对象内存分配和基本数据类型的默认值与初始化相关问题
- 返回table数据类型的函数相关的问题
- void相关的无类型变量在使用时必须强制数据类型转换问题。
- hibernate开发中的Date数据类型问题
- access中,有无将文本类型的数据格式转化成数值型的函数?(解决 order by 的非数字排序问题)
- asp.net读excle的数据类型不统一取出空值问题
- 通过强类型DataSet更新数据的问题。
- 添加用户记录时出现数据类型不匹配的问题。。。
- 游标类型产生的数据检索问题
- 在学习.net中的小问题,关于oledb 的日期数据类型