Java Double Float数值运算|精度缺失

Java中小数默认是double,整数默认int,例如你写4.0这种字面值,Java认为是double类型,你写4这个字面值,Java认为是int类型,你写float f = 4.0;Java就报错,原因有两个,一是4.0是double类型,二是double不能隐式转换为float(可以强转)。所以你要这样写:float f = 4.0f;或者:float f = (float)4.0;使用强转时,你必须知道你在做什么。

下面来说说精度缺失的问题,首先我们来说说浮点数的表示方式,计算机存储浮点数的方式是以科学计数法为理论依据的,科学计数法通常写作:2.123 x 10^(2),其中2.123是尾数(mantissa),10是基(base),2是指数(exponent)。IEEE 754-1985规定32位浮点数在计算机中存储的大致方式如下图:

在一些教材中我们可以看到他们讲解的是浮点数分为阶符、阶码、数符、尾数四部分,和上面的是不一样的,确实,这种方式比较简单,被教学采用,不被计算机采用。要想了解这些,还有许多基础知识需要了解,这里整理一些了,对于进制之间得转换一定要自己悟出其中的道理,我们思想中根深蒂固的是10进制,所有数据都不自觉的使用10进制而不自知,另外还有一些浅显的规则也没意识到,比如2进制只有0和1,2不属于2进制,每当在使用2做有关的运算时,很可能就是在做与10进制之间的交互运算。

1

十进制小数转换成二进制(乘2取整):

比如0.8125的二进制转换方式是:0.8125*2=1.6250得到整数部分1,0.6250*2=1.25得到整数部分1,0.25*2=0.5得到整数部分0,0.5*2=1得到整数部分1,因为小数部分为0,所以结束,0.8125的二进制表示就是0.1101。原理可以看下图,转换的时候就是要将小数部分的这些格子填入1或者0,要确定第一个格子是0还是1,就需要知道十进制小数是否大于等于0.5,将十进制小数乘以2,如果结果大于1,那么十进制小数肯定大于0.5,那么第一个格子就肯定为1,也即乘以2以后的整数部分,上面的1.6250就说明第一个格子是1,然后继续用小数部分乘以2,去掉整数部分意味着什么呢,就是去掉了1/2*2这部分,剩下的就要判断是否大于1/4,就要将小数部分继续乘以2,接下来的事情都是重复的了。但是这种转换得到的二进制并不是计算机中存储的浮点数。

2

IEEE 754标准表示的浮点数

浮点数的存储是有标准的,这样才能相互通信而不发生错误。IEEE 754规定规格化的浮点数表示x=(−1)S×(1.M)×2e

a、尾数用原码;

b、阶码用“移码”,IEE754规定浮点数阶码E采用”指数e的移码-1“来表示,为什么指数移码要减去1,这是IEEE754对阶码的特殊要求,以满足特殊情况,比如对正无穷的表示。

c、基为2;

d、浮点数需要规格化,若不对浮点数的表示作出明确的规定,同一个浮点数的表示就不是唯一的。例如(1.75)10(1.75)10可以表示成1.11×201.11×20,0.111×210.111×21,0.0111×220.0111×22等多种形式。当尾数不为0时,尾数域的最高有效位为1,这称为浮点数的规格化。否则,以修改阶码同时左右移动小数点位置的办法,使其成为规格化数的形式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值