Java进阶--从源码理解Math.ceil()、Math.floor()、Math.round()
来源:互联网 发布:fifo和lifo存货的算法 编辑:程序博客网 时间:2024/06/07 21:32
Math.ceil()
首先看看Math.ceil()定义:Math.ceil()是常见编程语言中的常用代码,ceil() 方法执行的是向上取整计算,它返回的是大于或等于函数参数,并且与之最接近的整数。下面特殊情况:
1.如果当前参数就是整数,直接返回。
2.如果当前参数不是数值型、无穷大,或者是正0和负0,直接返回当前参数。
3.如果当前参数小于0但是大于-1.0,则返回-0.
例如:
Math.ceil(12.2)//返回13.0
Math.ceil(12.7)//返回13.0
Math.ceil(12.0)// 返回12.0
Math.ceil(-0.8)//返回-0.0
然而光记这些概念是很容易遗忘的,如果能够弄懂Java api 到底是怎样实现,这样不但知其然,而且之前所以然,当然记忆的更加深刻。下面就一起走进Java api 吧。下面就是Math.ceil() 在Java api 中的实现代码。为了方便理解进行了一定的简化。
//ceil , floor 是 Math 类中的两个静态方法。public final class Math { public static double ceil(double a) { return floorOrCeil(a, -0.0, 1.0, 1.0); //在这里进行了一定的简化,floorOrCeil原本不在Math类中。 } public static double floor(double a) { return floorOrCeil(a, -1.0, 0.0, -1.0); //floor 也调用了floorOrCeil 方法 }}
原来 ceil 和 floor 方法都调用了一个 floorOrCeil();方法而且仅仅是在调用此方法的时候传入了不同的参数,下面就看看这个 floorOrCeil() 到底是什么。
private static double floorOrCeil(double a, double negativeBoundary, double positiveBoundary, double sign) { // int exponent = Math.getExponent(a); //exponent 是指的a的指数。如果 a=1.2*2^9,那么a的指数就是9。 if (exponent < 0) { /* * 如果a的指数小于0 那么可以肯定-1<a<1, * 此时如果a==0,则直接返回0,如果a<0,返回negativeBoundary * 在ceil 方法中negativeBoundary =-0.0 * 在floor方法中negativeBoundary =-1.0 */ return ((a == 0.0) ? a : ( (a < 0.0) ? negativeBoundary : positiveBoundary) ); } else if (exponent >= 52) { /* * exponent >= 52,则超出了double的范围,为无穷大,则直接返回。 */ return a; } // 如果 exponent >= 0 && exponent <= 51,在double范围内 assert exponent >= 0 && exponent <= 51; long doppel = Double.doubleToRawLongBits(a); //获得a的二进制格式。 long mask = 0xfffffffffffff >> exponent; //mask 是获得a的小数位的掩码,mask & doppel获得a的小数位,如果a的小数位为0那么a是整数,则直接返回。 if ( (mask & doppel) == 0L ) return a; // 整数 else { //result将a的小数部分去掉,获得a的整数。 double result = Double.longBitsToDouble(doppel & (~mask)); //sign=1,标识ceil调用,sign=-1,标识floor调用 if (sign*a > 0.0) result = result + sign; //如果a的小数部分不为0且是ceil 方法调用时,如果a>0,则:返回result+1,a<0,直接去掉小数部分。 //如果a的小数部分不为0且是floor方法调用时,如果a>0,则:返回result,a<0,返回result-1。 return result;
上面算法中重点要理解的是下面这行代码:
long doppel = Double.doubleToRawLongBits(a); long mask = 0xfffffffffffff >> exponent; if ( (mask & doppel) == 0L ) return a; else { double result = Double.longBitsToDouble(doppel & (~mask)); if (sign*a > 0.0) result = result + sign; }
其中 long doppel = Double.doubleToRawLongBits(a);
返回a的 IEEE 754 浮点数运算标准的二进制比特流。在这里以一张图来了解 IEEE 754 浮点数运算标准:
如果a=101.1 则用 IEEE 754 标准表示为:
指数大小为:1029-1023=6,其中:mask 的作用是用来获取小数部分的。 long mask = 0xfffffffffffff >> exponent ; mask 只有小数位上对应的值为1,其余为0,mask & doppel 获取小数部分。
double result = Double.longBitsToDouble(doppel & (~mask)); 获取整数部分。
总结一下ceil算法的流程:其实上面的算法分为以下几个步骤:
1.如果 a大于-1且小于1,如a大于-1且小于0则返回-0.0,否则返回1。
2.判断a是否超出了double的返回,如果超过了则直接返回a。
3.如果a为整数直接返回a。
4.获得a的整数部分b,如果a>0,返回b+1,否则直接返回b。
5.结束。
下面是算法的流程图:
最后一句话说一下Math.floor(),其实由上面的算法可以看出 Math.ceil(x)=-Math.floor(-x) 因此只要理解了ceil的实现方式 floor 就很容易理解了。
Math.round()
还是先直接上源码:
public static int round(float a) { if (a != 0x1.fffffep-2f) // 如果a不等于最接近0.5且比0.5小的浮点数值 return (int)floor(a + 0.5f); else return 0; }
上面代码很清楚其实 round(float a) 就是将a+0.5然后向下取整。例如:Math.round(11.5)=Math.floor(11.5+0.5)=12. Math.round(-11.5) =Math.floor(-11.5+0.5)=-11.
- Java进阶--从源码理解Math.ceil()、Math.floor()、Math.round()
- Math.ceil() 、Math.floor() 、Math.round() 三个函数的理解
- Math.round ceil floor
- Math.ceil()和Math.floor()、Math.round()
- Math.round|Math.floor|Math.ceil区别
- Math.floor,Math.round,Math.ceil
- Math.round, Math.ceil 和 Math.floor
- Math.floor()/Math.ceil()/Math.round()
- Math.ceil、Math.floor、Math.round用法
- java 中 Math.round() Math.ceil() Math.floor()区别
- java中Math.round(),Math.ceil(),Math.floor()运算
- Java中Math.round(),Math.floor(),Math.ceil()的理解和总结
- java math.ceil() floor()
- JS:Math.random(),Math.ceil(),Math.floor()与Math.round()
- Math.random()、Math.ceil()、Math.floor()、Math.round()
- Math.floor,Math.ceil,Math.rint,Math.round用法详解
- Math.floor,Math.ceil,Math.rint,Math.round用法详解
- Math.floor,Math.ceil,Math.rint,Math.round用法详解
- STL源码剖析-关联式容器之hashtable
- J2EE系列之Struts2学习笔记(二)---使用get/set方法自动获取/设置参数值
- spring security增加图形验证码
- C++常成员
- 《JavaScript面向对象编程》笔记1(函数)
- Java进阶--从源码理解Math.ceil()、Math.floor()、Math.round()
- 二叉树的层次遍历
- sublime text 3 + python配置,完整搭建及常用插件安装
- Hive学习(三)-集合数据类型
- Problem E: 编写函数:Swap (I) (Append Code)
- 拦截器 Interceptor
- u-boot中mkimage工具的具体使用
- 关于javax.validation.Validator校验的使用
- json的另外一种写法