Math工具类的ceil()、floor()、round()方法源码阅读

目录

浮点数的表示

 移码

Math工具类中的ceil(double)和floor(double)方法

 第一行通过Math.getExponent()方法得到了浮点数的阶码值。

然后判断阶码的值是否小于0

然后判断阶码是否大于等于52

阶码在0到51之间

对消去小数部分的结果进行调整

如果传入的值为负数

如果传入的值为正数

Math.round(double)方法


浮点数的表示

 以double数据类型为例:

符号位S63位

0表示这个浮点数为正数

1表示这个浮点数为负数

阶码E62-52位2^E表示这个浮点数的指数
尾数M52-0位表示这个浮点数

计算一个double数值类型的数据

data = (-1)^S * M * 2^E

在计算机中存储时,阶码采用移码-1的方式存储,尾数只存储小数部分

 移码

移码就是对补码的符号位进行取反。

Math工具类中的ceil(double)和floor(double)方法

 

Math.ceil(double)里面调用了StrictMath.ceil(double);

Math.flooor(double)里面调用了StrictMath.floor(double)。

在 StrictMath类中的ceil(double)和floor(double)都调用了floorOrCeil(double,double,double,double)方法。

 第一行通过Math.getExponent()方法得到了浮点数的阶码值。

Math.getExponent()方法源码

然后判断阶码的值是否小于0

因为阶码E需要转换成*2^E的指数表示方式*2^E可以用左移E位(<<E)来表示。如果E小于0,则数据右移,尾数M需要表示为1.M,当数据右移,无论几位,整数部分都会变成0,即这个数在-0.9999~0.999之间。

如果这个值为0.0,则返回这个值,如果小于0则返回规定的负值,如果大于0返回规定的正值(在StrictMath.ceil()中正边界为1.0,负边界为-0.0,在StrictMath.floor()中正边界为0.0,负边界为-1.0)。

然后判断阶码是否大于等于52

阶码大于等于52则全部的尾数都用来表示整数部分了也不够,这个传入的数据过大,直接返回这个数据。

阶码在0到51之间

先获取到浮点数的二进制表示deppel

mask的1的长度和小数部分的长度一致。

如果mask & deppel的结果0表示小数部分为0,之间返回这个浮点数。

否则使用(deppel & (~mask))抹去浮点数的小数部分(波浪号表示按位取反,mask按位取反之后,与deppel相对应的小数部分全为0,其它部分全为1,相与就可以取出deppel的小数部分)。

对消去小数部分的结果进行调整

ceil()传入的sign为1.0,floor传入的sign为-1.0

如果传入的值为负数

ceil()中sign*a小于0,结果不需要调整。(负数向上取整,直接抹去小数部分)

floor()中sign*a大于0,结果加上sign就是结果-1(负数向下取整,抹去小数部分,整数部分-1)

如果传入的值为正数

ceil()中sign*a大于0,结果加上sign激素结果+1(正数向上取整,抹去小数部分,整数部分+1)

floor()中sign*a小于0,结果不需要调整。(负数向上取整,直接抹去小数部分)。

Math.round(double)方法

先获取到传入数值的二进制表示。

shift保存了阶码-1。

获取到尾数并补充尾数最前面的1(浮点数保存的尾数会省略最前面的1)。并添加符号,保存为r。

当r右移>>shift位时,由于shift等于阶码-1,r>>shift = r*2^(E-1),相当于a*2

(r>>shift) + 1相当于a*2+1

((r>>shift) + 1)>>2相当于(a*2+1)/2

所以Math.round()方法可以看做对原值+0.5再向下取整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值