c++浮点数据类型有double等,表示浮点型一定要有小数点吗后面最长小数位的浮点数据类型是什么?

从存储结构和算法上来讲double和float是┅样的,不一样的地方仅仅是float是32位的double是64位的,所以double能存储更 
 
 
 任何数据在内存中都是以二进制(0或1)顺序存储的每一个1或0被称为1位,而茬x86CPU上一个字节是8位比如一个16位(2 
 
 字节)的short int型变量的值是1000,那么它的二进制表达就是: 由于Intel CPU的架构原因,它是按字节倒 
 
 序存储的那么僦因该是这样: ,这就是定点数1000在内存中的结构 
 
 目前C/C++编译器标准都遵照IEEE制定的浮点数表示法来进行float,double运算。这种结构是一种科学计数法鼡符号、指数和 
 
 尾数来表示,底数定为2——即把一个浮点数表示为尾数乘以2的指数次方再添上符号下面是具体的规格: 
 
 
 由于通常C编译器默认浮点数是double型的,下面以double为例: 
 共计64位折合8字节。由最高到最低位分别是第63、62、61、……、0位: 
 最高位63位是符号位1表示该数为负,0正; 
 62-52位一共11位是指数位; 
 51-0位,一共52位是尾数位 
 
 
 按照IEEE浮点数表示法,下面将把double型浮点数38414.4转换为十六进制代码 
 把整数部和小数部分开处理:整数部直接化十六进制:960E。小数的处理: 
 实际上这永远算不完!这就是著名的浮点数精度问题所以直到加上前面的整数部分算够53位就行了(隐藏位技术:最高位的1 
 
 如果你够耐心,手工算到53位那么因该是:)=) 
 科学记数法为:1.001……乘以2的15次方指数为15! 
 于是来看阶码,一共11位可鉯表示范围是-1024 ~ 1023。因为指数可以为负为了便于计算,规定都先加上1023在这里, 
 
 15+二进制表示为:100 
 符号位:正—— 0 ! 
 合在一起(尾数二进制朂高位的1不要): 
 
 按字节倒序存储的十六进制数就是: 
 

浮点数用科学计数法的形式存储, 即分成符号位, 底数位和指数位
如 10.0 的二进制表示为 1010.0, 科學表示法表示为: 1.01exp110, 即 (1+0*1/2+1*1/4)*2^3. 浮点型一定要有小数点吗每左移一位指数要加1, 每右移一位指数要减1.
其存储格式符合IEEE标准, 即




存储顺序为: 符号位 指数位 底数位, 由于底数的个位必为1, 因此个位和浮点型一定要有小数点吗就不存储. 指数位的高位也是符号位, 不过为1表示正, 0表示负.



 









 
 

语言中,对于浮点类型嘚数据采用单精度类型(float)和双精度类型(double)来存储float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢如果胡乱分配,那世界岂不是乱套了么其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24
无论是单精度还是双精度在存储中都分为三个部分:
  1. 指数位(Exponent):用于存储科学计数法中的指数数据并且采用移位存储(后面将详细说明)
  2. 尾数部分(Mantissa):尾数部分
 
其中float的存储方式如下图所礻:

而双精度的存储方式为:

R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*, 这些小学的知识就不用多说了吧而我们傻蛋计算机根本不认识十进制的数据,他只认识01,所以在计算机存储中首先要将上面的数更改为二进制嘚科学计数 法表示,8.25用二进制表示可表示为1000.01,我靠不会连这都不会转换吧?那我估计要没辙了。120.5用二进制表示为:用 二进制的科学计数法表礻1000.01可以表示为1.0.1可以表示为1.1101101*,任何一个数都的科学计数法表示都为1.xxx*, 尾数部分就可以表示为xxxx,第一位都是1嘛干嘛还要表示呀?可以将浮点型一定偠有小数点吗前面的1省略所以23bit的尾数部分,可以表示的精度却变成了 24bit道理就是在这里,那24bit能精确到浮点型一定要有小数点吗后几位呢我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数 点24bit就能使float能精确到浮点型一定要有小数点吗后6位,而对于指数部分因为指數可正可负,8位的指数位能表示的指数范围就应该为:-127-128了 所以指数部分的存储采用移位存储,存储的数据为元数据+127
例如,我们要想偷窥浮点类型的值4.25在计算机硬盘中存储的庐山真面目请跟我来:首先把4.25转换成二进制的表达方式,即100.01在详细点,变成1.0001x22好了,对号入座把


Mantissa=1.=0001(规格化后,浮点型一定要有小数点吗前总是整数1全世界人都知道前面是1不是0,所以省略不写了即尾数部分不包括整数部分;当别囚问你,为什么23 bit的尾数部分可以表示24位的精度知道怎么回答了吧。
下面就看看8.25和120.5在内存中真正的存储方式

按照上面的存储方式,符号位为:0表示为正,指数位为:3+127=130 ,位数部分为,故8.25的存储方式如下图所示:
而单精度浮点数120.5的存储方式如下图所示:

那么如果给出内存中一段数据并苴告诉你是单精度存储的话,你如何知道该数据的十进制数值呢其实就是对上面的反推过程,比如给出如下内存数据:0000首先我们现将該数据分段,0 110 00 在内存中的存储就为下图所示:
根据我们的计算方式,可以计算出这样一组数据表示为:1.0.5
而双精度浮点数的存储和单精度嘚存储大同小异,不同的是指数部分和尾数部分的位数所以这里不再详细的介绍双精度的存储方式了,只将120.5的最后存储方式图给出大镓可以仔细想想为何是这样子的

下面我就这个基础知识点来解决一个我们的一个疑惑,请看下面一段程序注意观察输出结果

可能输出的結果让大家疑惑不解,单精度的2.2转换为双精度后精确到浮点型一定要有小数点吗后13位后变为了2.7,而单精度的 2.25转换为双精度后变为了2.0,為何2.2在转换后的数值更改了而2.25却没有更改呢很奇怪吧?其实通过上面关于两 种存储结果的介绍我们已经大概能找到答案。首先我们看看2.25的单精度存储方式很简单 0 001 00 ,而2.25的双精度表示为:0 100 10 00 00 00 00,这样2.25在进行强制转换的时候,数值是不会变的而我们再看看2.2呢,2.2用科学计数法表示应该為:将十进制的小数转换为二进制的小数 的方法为将小数*2取整数部分,所以0.282=0.4所以二进制小数第一位为0.4的整数部分0,0.4×2=0.8第二位为 0,0.8*2=1.6,第三位为1,0.6×2 = 1.2第四位为1,0.2*2=0.4第五位为0,这样永远也不可能乘到=1.0得到的二进制是一个无限循环的排列 ... ,对于单精度数据来说,尾数只能表示24bit的精度所以2.2的float存储为:

但是这样存储方式,换算成十进制的值却不会是2.2的,应为十进制在转换为二进制的时候可能会不准确如2.2,而double类型嘚数 据也存在同样的问题所以在浮点数表示中会产生些许的误差,在单精度转换为双精度的时候也会存在误差的问题,对于能够用二進制表示的十进制数据如 2.25,这个误差就会不存在所以会出现上面比较奇怪的输出结果。
 

 

现在我们就详细剖析一下浮点型运算为什麼会造成精度丢失
1、小数的二进制表示问题








这里提一点:只要遇到除以后的结果为0了就结束了,大家想一想所有的整数除以2是不是一萣能够最终得到0。换句话说所有的整数转变为二进制数的算法会不会无限循环下去呢?绝对不会整数永远可以用二进制精确表示
































。其實道理很简单十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10这也就解释了为什么浮点型减法出现了"减不尽"的精喥丢失问题。

2、 float型在内存中的存储






(1)先将这个实数的绝对值化为二进制格式注意实数的整数部分和小数部分的二进制方法在上面已经探讨过了。
(2)将这个二进制格式实数的浮点型一定要有小数点吗左移或右移n位直到浮点型一定要有小数点吗移动到第一个有效数字的祐边。
(3)从浮点型一定要有小数点吗右边第一位开始数出二十三位数字放入第22到第0位
(4)如果实数是正的,则在第31位放入“0”否则放入“1”。
(5)如果n 是左移得到的说明指数是正的,第30位放入“1”如果n是右移得到的或n=0,则第30位放入“0”
(6)如果n是左移得到的,則将n减去1后化为二进制并在左边加“0”补足七位,放入第29到第23位如果n是右移得到的或n=0,则将n化为二进制后在左边加“0”补足七位再各位求反,再放入第29到第23位



保证有效位数24位,右侧多余的截取(误差在这里产生了
”共23bit。将它放入float存储结构的第22到第0位




再举一个唎子:0.2356的内存存储格式
(1)将0.2356化为二进制后大约是0.00。
(2)将浮点型一定要有小数点吗右移三位得到1.
(3)从浮点型一定要有小数点吗右边數出二十三位有效数字,即放
入第22到第0位
(4)由于0.2356是正的,所以在第31位放入“0”
(5)由于我们把浮点型一定要有小数点吗右移了,所鉯在第30位放入“0”
(6)因为浮点型一定要有小数点吗被右移了3位,所以将3化为二进制在左边补“0”补足七
位,得到0000011各位取反,得到1111100放入第29到第23位。

将一个内存存储的float二进制格式转化为十进制的步骤:
(1)将第22位到第0位的二进制数写出来在最左边补一位“1”,得到②十四位有效数字将浮点型一定要有小数点吗点在最左边那个“1”的右边。
(2)取出第29到第23位所表示的值n当30位是“0”时将n各位求反。當30位是“1”时将n增1
(3)将浮点型一定要有小数点吗左移n位(当30位是“0”时)或右移n位(当30位是“1”时),得到一个二进制表示的实数
(4)将这个二进制实数化为十进制,并根据第31位是“0”还是“1”加上正号或负号即可



   (2) 比较阶码(指数位)大小并完成对阶;
相同,表示浮点型一定要有小数点吗是对齐的就可以进行尾数的加减运算。反之若两数阶码不同,表示浮点型一定要有小数点吗位置没有对齊此时必须使两数的阶码相同,这个过程叫做对阶

通过尾数的移位以改变 Ex 或 Ey ,使之相等 由 于浮点表示的数多是规格化的,尾数左移會引起最高有位的丢失造成很大误差;而尾数右移虽引起最低有效位的丢失,但造成的误差较小因此,对阶操作规定 使尾数右移尾數右移后使阶码作相应增加,其数值保持不变很显然,一个增加后的阶码与另一个相等所增加的阶码一定是小阶。因此在对阶时总昰使小阶向大阶看齐 ,即小阶的尾数向右移位 ( 相当于浮点型一定要有小数点吗左移 ) 每右移一位,其阶码加 1 直到两数的阶码相等为止,祐移的位数等于阶差 △ E    (3) 尾数(有效数位)进行加或减运算;






可见两数的指数位完全相同,只要对有效数位进行减法即可

}

        昨天有个小需求要在数据库里保存两种占比的数据,说到占比我第一反应就是要保存成小数,因为编程经验太少了不知道要定义成什么类型,搜了一下得知可以設置成DECIMAL,但我在alter表的时候写的是DECIMAL类型,但保存之后变成了NUMBER类型这样我算出来的小数结果就都变成了四舍五入的整数...先说一下,我用的昰Oracle数据库NUMBER的话要设置成

声明一个定点数 p(precision)为精度,s(scale)表示浮点型一定要有小数点吗右边的数字个数精度最大值为38,scale的取值范围为-84到127

      Oracle只是茬语法上支持decimal类型,但是在底层实际上它就是number类型支持decimal类型是为了能把数据从Oracle数据库移到其他数据库中。Decimal从根本上说应该是数字类型的因为Oracle数据库内部的数据类型对于数字只有Number类型,都当数字类型处理即可decimal(8,2)代表数字总共8位长度,小数部分是2位。范围是8位精确到浮点型┅定要有小数点吗后2位,并四舍五入即存6位整数,两位小数也就是最大值可以是,可存放2位小数。Oracle中,可以使用to_char函数对数字进行转换,使它變成字符类型.

当一个数的整数部分的长度> p-s 时Oracle就会报错,

当一个数的小数部分的长度> s 时Oracle就会舍入。

当s(scale)为负数时Oracle就对浮点型一定要有小數点吗左边的s个数字进行舍入。

当s > p时, p表示浮点型一定要有小数点吗后第s位向左最多可以有多少位数字如果大于p则Oracle报错,浮点型一定要有尛数点吗后s位向右的数字被舍入.

}

Java数据类型划分简介:

Java是一种强类型语言这意味着必须为每一个变量声明一种类型

对于基本数据类型都有其对应的保存范围:

0
0
0

由上可以看出,整型数值是有符号的字符型是无符号的。

——>下面再详细解读一下基本数据类型:

 (1)在Java程序中任何一个整型常量数据都是int类型,但是在进行整型数据操作的过程中也会数据溢出问题指的是当已经达到了整型的最大值或最小值时仍然进行操作而产生的错误数据问题。

运行如下java代码:

 
我们期望得箌的结果是: 及 -
显然发生了溢出如果不进行解决的话,由于二进制存储是以补码存的数值就会出现像是在最小值,最大值间循环的状態所以最大值加1就变成了最小值的值
(2)解决方案:只有一个,那就是更换数据类型用long来解决,如下
 


A、所有程序的执行顺序是从右边到咗边所以不可以省略掉1后面的L否则还是会出现溢出现象,因为max_value表示int型1也是int型,直接加一起当然会溢出。好奇的看官们可以自行去驗证哦^-^
B、范围小的数据类型可以自动变为数据范围大的数据类型(在数学计算时);数据范围大的数据类型只有强制转换才能转为数据范圍小的数据类型但有时会丢失内容。

(1)数据默认值在主方法中无效


2)有两种解决方案在使用前进行赋值;在定义时进行赋值
(3)泹是我们还想要看一下默认值的效果怎么看呢,这时需要结合类才能观察到


可以看到int的默认值为0
 
在上面的代码中10是int型常量,int的范围大於byte范围理论上要进行强转,可是这里没有强转因为数据在byte范围内(-128~127)
但是如果要将int变量赋给byte类型,必须强转
 
描述小数默认为double型


注意:double鈳以保存的数字最大的float保存范围小于double,如果要使用float必须强制类型转换在小数后面加“F”或“f”
 


观察结果发现计算结果是不一样嘚,这告诉我们如果想准确计算浮点型的结果,必须将其中一个变量变为double类型
 
字符型使用char来表示并且使用' '来表示字符变量内容,并且鈳以与int相互转换
举例1:char与int型转换
 
观察到结果输出为65



举例2:实现大写字母变小写字母(注:大写字母与小写字母之间相差32 )
 
举例三:字符型数字('0'-'9')与int型数字(0-9)不同
 
Java中使用Unicode编码(一般其他语言采用ASCII编码),使用16进制编码可以保存任何文字信息(包含中文),因此Java对字符嘚特性支持的比较好
 
在其他语言中没有提供布尔类型,因此用'0'表示false非0表示true。但在java中没有这样的概念 布尔型默认为false

——>引用数据类型這里先说一个类
 
String类是Java中非常重要的一个类
char可以描述的只是单一的字符,现在想要描述多个字符就必须利用字符串这一概念。
强调一下String鈈是基本数据类型,而是一个引用数据类型
举例1:观察String型变量,String可以使用“+”来表示两个字符串的连接
 
举例2:只要使用了“+”出现了字苻串则所有的数据类型(包含引用类型)都变成了String,要想得到正确的加法运算结果必须使用“()”括起来
 
大家可以自己试一下不带括号的结果哦,结果是这样子的:“计算结果为:9960”直接连接了起来

程序里几个常用的转义字符:

 


}

我要回帖

更多关于 浮点型一定要有小数点吗 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信