-
为什么float类型可以接收long类型?(为什么float比long范围大)
2021-02-07 16:00:45目录IEEE754浮点数标准指数位确定范围小数位确定精度总结 转换原则(低精度向高精度转换):byte->(short,char)->int->long->float->double IEEE754浮点数标准 IEEE754标准包含一组实数的二进制...- 转换原则(低精度向高精度转换):byte->(short,char)->int->long->float->double
IEEE754浮点数标准
- IEEE754标准包含一组实数的二进制表示法。它有三部分组成:符号位, 指数位, 尾数位
- 三种精度的浮点数各个部分位数如下:
精度 符号 阶/指数 尾数 单精度 1 8 23 - 第一部分用来存储符号位(sign),用来区分正负数,0正1负。
- 第二部分用来存储指数(exponent),指数也有正负之分,指数位确定大小范围。
- 第三部分用来存储小数(fraction),小数位决定了计算精度,因为小数位能表示的数越大,精度越大,数值越准确。
指数位确定范围
- 指数可能是负数,也有可能是正数。而有符号整数的计算是比无符号整数麻烦的。所以为了减少不必要的麻烦,在实际存储指数的时候,需要把指数转换成无符号整数。
- 我们看到float的指数部分是8位,则指数的取值范围是 -126到+127,为了消除负数带来的实际计算上的影响(比如比较大小,加减法等),可以在实际存储的时候,给指数做一个简单的映射,加上一个偏移量,比如float的指数偏移量为127。
小数位确定精度
- float和double的精度是由尾数的位数来决定的。
- float:2^23 = 8388608,一共七位,由于最左为1的一位省略了,这意味着最多能表示8位数,但绝对能保证的为7位,也即float的精度为7~8位有效数字(算上整数的一位)
- double:2^52 = 4503599627370496,一共16位,同理,double的精度为16~17位
总结
- long:2^63-1;
- float : float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38
- 所以:float的数据范围大于long的数据范围
-
【c++】为什么int和float类型都占有4个字节,但是float类型表示范围却比int类型大好多?
2018-12-08 18:11:12原因很简单,就是int类型是直接以二进制形式保存,而float类型是以指数形式保存。 下面内容对于初学者来说如果继续看下去收获肯定会不小,但是也会有一定的挑战,但还是希望你静下心,认真看下去。 目录一、背景二...- 原因很简单,就是int类型是直接以二进制形式保存,而float类型是以指数形式保存。
- 下面内容对于初学者来说如果继续看下去收获肯定会不小,但是也会有一定的挑战,还是希望你静下心,认真看下去。
一、背景
- 这几天在写《算法设计与分析的作业》期间遇到了用int和float类型最大值,初始化变量的问题。查了一下,int可以用<limits.h>中的INT_MAX初始化,float可以用<float.h>中的FLT_MAX初始化,但是我就很难受,为什么都是基本类型的最大值,却要包含两个头文件,能不能偷懒,用int最大值直接去初始化float或者float最大值初始化int呢?按照以前的错误理解,int和float字节数相同,但是float有小数部分,所以它表示的范围更窄,我呢就写了一个程序看了下,这两个到底相差多大,偷懒的做法风险有多高,所以就写了下面的程序:
#include <iostream> #include <limits.h> #include <float.h> using namespace std; int main() { cout<<INT_MAX<<endl; cout<<FLT_MAX<<endl; return 0; }
结果如下:
- 不试不知道,一试吓一跳啊,float的表示范围怎么会那么大,该不会他们使用的内存空间不一样吧:
#include <iostream> #include <limits.h> #include <float.h> using namespace std; int main() { cout<<INT_MAX<<endl; cout<<FLT_MAX<<endl; cout<<sizeof(int)<<endl; cout<<sizeof(float)<<endl; return 0; }
- 结果:
- 果然是我太菜了,那就好好看下到底是怎么回事吧:
二、int类型分析
1、分析
- int 用4字节保存,最多表示, 有正数和负数,所以可表示个正数,即其最大值为2147483647,和上面结果一致,最小值-2147483648, 最大值比最小值的绝对值小1, 这是因为0占据了正数的一个表示名额。
- 具体如下:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - 总共32位,也就是说它的能存储的数字就是32位全0,到32位全1。如果这 样的话它就只能存储正数了,但是我们计算也要用到负数,这可不太妙啊。所以为了能够即能存储正数又能够存储负数,科学家在设计计算机的时候把这32位数据进行了重新解释,从全0开始,一直到, 除最前一位之外,其余位都为1,这些表示他们对应的正数。就是下面这种形式
从全0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 到除第一位是0之外全都是1
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 上面范围都表示正数。可以计算一下,上面这个数刚好就是对应的最大的int类型。
- 剩下的都表示负数了,那么问题又来了,这些负数有分别是怎么表示的呢?
我们接着上面的分析,最大的正数表示形式(就是上面写出来的除第一位是0之外全都是1的那个形式)在加一,就成了下面的样子:
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 这个数被计算机解释为最小的负数,就是-2147483648,然后依次类推,32的表示形式每加1, 它所表示的形式也就加1,一直到最大的负数-1,32位表示形式就成了全1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 好了关于int存储大致解释清楚了,但是我掌握的这些到底对不对呢?下面我们使用汇编来看一下,到底是不是这样:
2、验证(汇编)
- 这里用mips汇编来查看其存储方式, 把下面这段代码在汇编器Qtspim中运行(运行前请先删除汉字注释):
.data int_1: .word 0 ;定义了一个4字节的变量int_1,并把它赋值为0 int_2: .word 2147483647 ;定义了一个4字节的变量int_2,并把它赋值为2147483647 int_3: .word -1 ;定义了一个4字节的变量int_3,并把它赋值为-1 int_4: .word -2147483648 ;定义了一个4字节的变量int_4,并把它赋值为-2147483648 .text main: lw $t1,int_1 ;把上面定义的变量int_1取值到寄存器t1中 lw $t2,int_2 ;把上面定义的变量int_2取值到寄存器t2中 lw $t3,int_3 lw $t4,int_4
查看寄存器情况如下:
和上面解释的情况相同。三、float类型分析
1、分析
- float同样也是4字节保存只不过他的保存形式式如下:
- 也就是说第一个位置是符号位,如果它为0表示正数,为1表示负数
- 第2-9位共8个位是指数位,这里的指数位使用的是带偏阶的计数法1,就是说,这里存储的指数 = 真正指数+127,这里的127是它的偏阶。那么它最大能够存储多大的指数呢,8位最多能表示个数字也就是255个数字,从全0(0)到全1(255)。但是IEEE754的指数全1是不能表示数字的;真正指数 = 这里存的指数-127,所以最大能够存储的指数是254-127 = 127,最小能够存储的指数是1-127 = -126,这里最小用了1减,而没有用0,是因为当指数为0,而尾数非0,这不是规格化数。所以最终指数部分能够表示的范围是-126 ~ 127
- 在看尾数部分,IEEE754隐藏了一个前导1,也就是说,这里存储的尾数 = 真正尾数 - 1,所以我们在将存储的数据还原为原先的数据时一定要加上1.
2、验证(汇编)
.data float_1: .float -0.5 float_2: .float 0.0 float_3: .float 3.1875 .text main: lw $t1,float_1 lw $t2,float_2 lw $t3,float_3
结果如下:
结果分析:- -0.5, 是负数所以第一位为1,0.5 = = . 所以它的指数部分应该是-1+127 = 126 = ,尾数1.0,隐藏1,最终结果和上面的一致。
- 0,符号位0和1都行,只要指数和尾数部分都为0即可。
- 3.1875 化成二进制就是(十进制浮点数化为二进制),然后科学计数法表示为*,这样指数部分为1,1+127 = 128,华为二进制就是尾数部分去掉隐藏的1,就是,上面显示时,t3要比t1少一位,这是因为t3是正数,显示时省略了符号位0。
-
1.Float型数据32位,与int相同,但float的表数范围远比int大,为什么
2019-04-11 09:56:17这个涉及到浮点数的结构(符号...2.指数部分有偏移量(float为127,double为1023) 3.规格化的表示小数点左边一定为1.(二进制数) 4.float类型符号位占1位,指数部分占8位,尾数占23位(因为规格化表示,小数点左边...这个涉及到浮点数的结构(符号位,指数部分,尾数部分),以及规格化的表示和非规格化的表示。
这里不详细解释,LZ可查阅相关资料
有几个知识点:
1.计算机中浮点数的基数是2.
2.指数部分有偏移量(float为127, double为1023)
3.规格化的表示小数点左边一定为1.(二进制数)
4.float类型 符号位占1位,指数部分占8位,尾数占23位(因为规格化表示,小数点左边一定为1,所以实际有24位精度)
5.double类型 符号位占1位,指数部分占11位,尾数占52位(因为规格化表示,小数点左边一定为1,所以实际有53位精度)
看一个例子float 0.6吧:
第一步,把十进制转2进制:
0.6的二进制表示(乘2取整,顺序表示):
.1001 1001 1001 1001 1001 1001 1001 ... 无限循环下去。
第二步,计算尾数部分:
把.1001 1001 1001 1001 1001 1001 1001 ...规格化表示(小数点移到第一个非0书右边)就是:
1.001 1001 1001 1001 1001 1001 1001 ...,右移了1位。
由于规格化表示的数小数点左边一定为1,把这个1舍弃,并保留float尾数能表示的23位,最终尾数部分是:
001 1001 1001 1001 1001 1001
第三步,计算指数部分:
由于计算尾数时右移了1位,相当于乘以2的负1次,所以指数为-1,加上float偏移量127,最后指数为126,
二进制表示为 0111 1110
第四步,符号部分:
0.6为正数,符号位为0
最终0.6在计算机中的表示就是:
符号位 指数 尾数
0 0111 1110 001 1001 1001 1001 1001 1001
--------------------------------------------------------------
我们再从这个2进制来计算10进制数:(2的指数次 * 尾数)
符号位0--> 为正
指数 0111 1110:为126, 减去偏移量127,结果为-1.
尾数 001 1001 1001 1001 1001 1001: 规格化的时候小数点左边人掉了一个1,现在加上:
1.001 1001 1001 1001 1001 1001,转为10进制就是:
1*2^0 + 1*2^-3 + 1*2^-4 + .....= 1.19999992847442626953125
1.19999992847442626953125 * 2^-1 = 0.599999964237213134765625
所以最终结果是一个无限接近于0.6而不能精确表示0.6具体更详细的解释和相关知识点,可以自行查阅以及参考收藏中的相关文章介绍
-
为什么浮点数比int,long表示的范围要大?
2019-01-18 16:32:32背景:float 底层用4个字节32位来表示,为什么范围比int,long还要大? 整数在计算机底层采用补码的形式表示,除去首位的符号位,剩余的位数即表示数值的范围,也就是位数越多,范围越大,那么对于单精度浮点数...背景:float 底层用4个字节32位来表示,为什么范围比int,long还要大?
整数在计算机底层采用补码的形式表示,除去首位的符号位,剩余的位数即表示数值的范围,也就是位数越多,范围越大,那么对于单精度浮点数float,和双精度浮点数double,它们底层的数据结构是什么,它们的范围又是如何计算的,它们的精度范围又是多少那,接下来将从6方面进行阐述。
1 IEEE754浮点数标准
IEEE754标准包含一组实数的二进制表示法。它有三部分组成:
- 符号位
- 指数位
- 尾数位
三种精度的浮点数各个部分位数如下:
用float来举例:
第一部分用来存储符号位(sign),用来区分正负数,0正1负。
第二部分用来存储指数(exponent),指数也有正负之分,指数位确定大小范围。
第三部分用来存储小数(fraction),小数位决定了计算精度,因为小数位能表示的数越大,精度越大,数值越准确。
备注:浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”
2 第二部分(指数位确定范围)
需要注意的是指数可能是负数,也有可能是正数,即指数是有符号整数,而有符号整数的计算是比无符号整数麻烦的。所以为了减少不必要的麻烦,在实际存储指数的时候,需要把指数转换成无符号整数。
那么怎么转换呢?注意到float的指数部分是8位,则指数的取值范围是 -126到+127,为了消除负数带来的实际计算上的影响(比如比较大小,加减法等),可以在实际存储的时候,给指数做一个简单的映射,加上一个偏移量,比如float的指数偏移量为127,对应的double类型,存储的时候指数偏移量是1023,这样就不会有负数出现了。
3 第三部分(小数位确定精度)
float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
float:2^23 = 8388608,一共七位,由于最左为1的一位省略了,这意味着最多能表示8位数,但绝对能保证的为7位,也即float的精度为7~8位有效数字(算上整数的一位),不算整数位的话能只有7位,所以能准确表示的10进制也就6位。
double:2^52 = 4503599627370496,一共16位,同理,double的精度为16~17位,能准确表示的10进制也就15位。4 注意点
- 程序中应尽量避免浮点数的比较,例如System.out.println(2.00-1.10==0.90),永远返回false.
- float、double类型的运算往往都不准确
5 正确的方式
- 利用整数来表示小数int或者long,例如1.01元,则可以以分为单位来表示。
- 利用BigDecimal进行浮点型运算,但是注意一定要使用String类型的构造方法,如果使用浮点型构造方法也不能得到准确的结果。
6 福利彩蛋(浮点数保留2位的几种方法)
1> double dd = (double) (Math.round(1/(float)num*100)/100.0); //先乘以100后除以100,对浮点数做进位处理。
2> DecimalFormat df=new DecimalFormat("###.00")
3>String ss = String.format("%1.2f", 1.1256);
4> NumberFormat ddf1=NumberFormat.getNumberInstance() ; ddf1.setMaximumFractionDigits(2);
5> BigDecimal b = new BigDecimal(T); T = b.setScale(2,BigDecimal.ROUND_HALF_UP).floatValue();
-
Java重学疑问--为什么float表示的数值范围比long大?
2020-07-21 21:35:21进行混合运算的时候 byte short char 不会相互转换 都会自动提升为int 取值范围大小如下 char < int < long < float <double double的取值范围最大 float的取值范围大于long 虽然 long的长度为8个... -
long与float的取值范围谁大谁小
2019-04-11 23:52:49进行混合运算的时候,byte、short、char不会相互转换,都会自动提升为int类型,其他类型进行混合运算是小数据类型提升为大数据类型。...为什么float比long的范围大呢?用一段代码看一下 通过代码可以看出,long类... -
Java int转float 精度损失
2020-09-13 17:21:42我起初的疑问,float取值范围比int取值范围大,为什么会出现精度损失那? 这里主要还是int和float底层的存储结构不同导致的。 int使用31位表示精度,float底层有23位来表示尾数,8位表示阶数。 这里精度主要是由这23... -
float浮点数存储方式以及int类型转换精度缺失问题心得
2019-03-22 19:32:53或许大家在刚接触时都会有疑问 虽然int类型与float类型的存储字节大小都是4字节,而且float的取值范围比int更大,为什么int类型转换为float类型是会发生精度缺失? 这要先从float类型的存储方式说起。 float在内存中... -
java基本数据类型 byte、short、int、long、float、double、char的范围和运算中注意的事项(详细)
2019-03-09 17:31:49①为什么float占4个字节,而long占8个字节,float表示的范围却比long要大得多呢? 原因简单说是因为二者存储的模式不同,long类型是是直接用64位二进制位去存储数据的二进制原码,而float作为浮点数类型,在java里遵循IEEE... -
Float计算机表示形式
2019-07-07 01:44:00float为什么比int表示的...java中int占用4个字节,float也是占用4个字节,但是为什么float表示的范围要比int大呢,因为两者在计算机内中表示的方式不一样,int是4个字节32位,每一位都是二进制小数表示,最高位0代表... -
int和Integer有什么区别?
2020-05-28 23:21:07文章目录正文简单的区分自动装箱 / 自动拆箱原始数据类型包装类补充为什么一个字节的范围是-128~127,而不是-127~127?Java 对象要比原始数据类型开销大的多。你知道对象的内存结构是什么样的吗?比如,对象头的... -
浅谈float和double
2020-04-25 17:56:46都知道int和float在Java中所占的字节数都是4字节,但是int只能存储整数型,float不仅能储存浮点型,存储范围也比整数大,既然同样的字节数为什么会有不同的效果呢? 是因为float和double类型在计算机中的存储结构... -
float浮点运算
2013-09-09 14:27:56有些C语言书上说float型的有效位数是6~7位,为什么不是6位或者7位?而是一个变化的6~7位?... float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么flo -
判断double_浅谈float和double
2021-01-12 14:08:49都知道int和float在Java中所占的字节数都是4字节,但是int只能存储整数型,float不仅能储存浮点型,存储范围也比整数大,既然同样的字节数为什么会有不同的效果呢?是因为float和double类型在计算机中的存储结构和... -
浮点数
2017-11-20 22:19:39浮点数的转换1.将浮点数转换成二进制2.用科学技术法表示二进制浮点数3.计算指数偏移后的值注意:计算指数偏移后的值...1029float和int在内存中都占4个字节,为什么float却比int所表示的范围大很多?1.float所表示... -
浮点数表示问题
2019-09-05 15:46:38关于为什么相同位数 ,int 精度范围更高,float表示范围更大的问题? 答: int32 在内存中的分配是:1bit(符号位)31bits(实际数字位) float 在内存中的分配情况是:1bit(符号位) 8bits(指数位) 23bits(尾数... -
java基础及面试题(1.1)
2021-01-20 03:06:39这里是对应java基础及面试题(1.0)的重要面试题 ...long到float不用强转,因为float表示的范围确实比long表示的范围大,虽然它只占4个字节,而long占8个字节,float是用科学记数法来表示数据的,long是用二进 -
c浮点数运算
2017-09-25 22:24:47有些C语言书上说float型的有效位数是6~7位,为什么不是6位或者7位?...float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9 -
浮点数运算
2015-05-26 14:49:58float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9.87654322不成立?为何10.2 - 9的结果不是1.2,而是1.1999998?为何98765 -
基本数据类型操作一:C语言浮点数解惑
2014-10-29 10:06:24前言 有些C语言书上说float型的有效位数是6~7位... float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9.87654322不成立?为何10.2 - -
C语言浮点数解惑
2013-08-12 19:15:49前言 有些C语言书上说float型的有效位数是6~7位,... float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9.87654322不成立?为何10.2 - -
关于基本数据类型以及数据类型之间的转换的回顾
2020-11-10 21:32:03(为什么double型数据范围比long型范围大,因为double型数据是按照特别格式存储数据的) 自动数据类型提升 byte -->short ==char -->int–>long–>float–>double 在基本数据类型的表达式运算中... -
C语言浮点数运算,讲述原理并总结一些案例
2014-03-04 16:07:24有些C语言书上说float型的有效... float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9.87654322不成立?为何10.2 - 9的结果不是1.2,而 -
C语言浮点数运算
2012-05-22 19:32:00float浮点数要比同为4字节的int定点数表示的范围大的多,那么是否可以使用浮点数替代定点数? 为什么float型浮点数9.87654321 > 9.87654322不成立?为何10.2 - 9的结果不是1.2,而是1.1999998?为何987654321 + ... -
Java语法基础学习DayTwo
2019-02-26 17:40:00一、数据类型补充问题 数据类型的自动转换等级: byte,short,char -- int -- long -- ...float表示的数据范围比long要大。 二、运算符 1.算术运算符+,-,*,/,%,++,-- %:任何整数模2不是0就是1,所以只要改变被...