偶然查看Math.round的JDK

1  public static int round(float a) {
2         if (a != 0x1.fffffep-2f) // greatest float value less than 0.5
3             return (int)floor(a + 0.5f);
4         else
5             return 0;
6     }

注释说0x1.fffffep-2f是最接近0.5的float类型的小数,咦,科学计数法用e表示指数我是知道的,但是这个p是什么鬼。可能有的读者还会问,为什么这个数时最接近0.5的数,这个数到底是多少呢?所以现在的问题有两个:

1、p代表什么。

2、0x1.fffffep-2f 用十进制表示到底是多少。

先公布答案,P在16进制表示的浮点数中代替e作为科学计数法指数部分的标志,1.fffffep-2f中的e是十六进制中的14;第二个问题很简单,也很复杂。说它简单是因为只需要几行代码就可以知道该值是多少。

System.out.println( 0x1.fffffep-2f);
BigDecimal bigDecimal=new BigDecimal(0x1.fffffep-2f);
System.out.println(bigDecimal.toPlainString());/*输出
0.49999997
0.4999999701976776123046875

说它复杂是理解它为什么是最近0.5的float数。

1、P究竟是什么

原来为了和十六进制中的e进行区分,在java中用16进制表示的浮点数,我们用P代替e作为指数的标志。所以该常数代表0x1.fffffe * 2^(-2),f(F)是float后缀,不写代表是double类型。

A floating-point literal has the following parts: a whole-number part, a decimal or hexadecimal point (represented by an ASCII period character), a fractional part, an exponent, and a type suffix. A floating point number may be written either as a decimal value or as a hexadecimal value. For decimal literals, the exponent, if present, is indicated by the ASCII letter e or E followed by an optionally signed integer. For hexadecimal literals, the exponent is always required and is indicated by the ASCII letter p or P followed by an optionally signed integer.

参考链接:https://stackoverflow.com/questions/8603232/p-in-constant-declaration/8603263#8603263(中文版Java语言规范3.10.2)

2、为什么是最接近0.5的数

任意一个二进制浮点数V可以表示成下面的形式:

 

  (1)(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。

  (2)M表示尾数,范围是[1,2)(规格化)或者是[0,1)(非规范化)。

  (3)2^E表示阶码。

IEEE 754规定,对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。e代表指数部分的无符号数ek-1ek-2...e0,f代表尾数部分的无符号数表示,0.fn-1...f1f0。

对于exp非零的数即规格化数而言,指数部分的取值范围E=e-127,是[-126,127],尾数部分是[1,2-2^(-23)](M=1+f)。

要得到最接近0.5的数,我们不能用1*2(-1),因为是完全相等。退而求其次,我们用2-2^(-23)*2(-2),一个非常接近2的数(3.9999998)除以4来表示0.5无疑是最正确的选择。

看到这里细心的读者可能会问,为什么不用一个非常接近4的数去除以8来到答案呢?无论十六进制浮点数写成0x1.fffffep2这种形式,还是写成0x3.3fffff这种尾数大于2的,Java内部都会通过调整阶码自动将尾数部分控制在[1,2)之间。所以无论使用3.99999(近似表示,下同)除以8还是7.9999999除以16,最后都要表示为一个尾数在[1,2)范围内,乘以一个阶码。换句话说,无论是用3.99999除以8还是7.9999999除以16最终的结果都是一样的。为了看起来比较直观,避免尾数转换之后精度丢失的麻烦,我们直接将尾数固定在[1,2)去确定阶码无疑是最正确的选择。

0x1.fffffep-2f二进制表示是 0 11111100 1111 1111 1111 1111 1111 111。

我们可以猜想对于double类型最接近0.5的数而言,应该同样是尾数全是1,阶码为-2。即为0x1.fffffffffffffp-2。

 public static long round(double a) {if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5return (long)floor(a + 0.5d);elsereturn 0;}

查看JDK,果不其然,说明我的分析是没有问题的。

(以上基础知识来自《深入理解计算机系统》2.4.2)

转载于:https://www.cnblogs.com/BJUT-2010/p/5551008.html

Java中浮点数的基础知识相关推荐

  1. Java中的线程基础知识

    Java中的线程基础知识 1.线程概念 线程是程序运行的基本执行单元.当操作系统(不包括单线程的操作系统,如微软早期的DOS)在执行一个程序时,会在系统中建立一个进程,而在这个进程中,必须至少建立一个 ...

  2. java中的greeting_JAVA基础知识——字符串

    1.从概念上讲,JAVA字符串就死Unicode字符序列,JAVA没有内置的字符串类型,而是在标准JAVA类库中提供了一个预定义类,叫做String.字符串用""括起来 2.子串: ...

  3. java中集合的基础知识_javaSE基础知识之集合类

    集合:Collection(是接口),集合用于存储一组元素.提供了维护集合的相关操作.其派生了两个子接口: List: 可重复集 .Set:不可重复集.元素是否重复,依靠元素自身的equals方法比较 ...

  4. java中的多态有哪些_简单了解Java中多态的基础知识

    一.多态 多态分为两种:(1)引用的多态.(2)方法的多态 引用的多态: 父类的引用可以指向本类的对象: 父类的引用可以指向子类的对象: 注意:子类的对象不可以指向父类的对象,如下图所示 方法的多态: ...

  5. 第90节:Java中的Linux基础

    第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686MYSQL依赖包: yum -y install libaio.so. ...

  6. python编程的基本方法有哪些_Python编程中常用的基础知识有哪些?

    今天小编要跟大家分享的文章是关于Python编程中常用的基础知识有哪些?正在从事Python相关工作的小伙伴们,来和小编一起看一看本篇文章,希望本篇文章能够对大家有所帮助. 1.正则表达式替换 目标: ...

  7. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  8. java最基本的基础知识

    java最基本的基础知识.这种东西应该印在脑子里雨打不动,风吹不走.以后不能为少个分号或缺个逗号之类的小问题所出错. 1.分隔符:超到分隔的作用. 有半角的分号(" ; ").逗号 ...

  9. 第87节:Java中的Bootstrap基础与SQL入门

    第87节:Java中的Bootstrap基础与SQL入门 前言复习 什么是JQ? : write less do more 写更少的代码,做更多的事 找出所有兄弟: $("div" ...

最新文章

  1. opencv上gpu版surf特征点与orb特征点提取及匹配实例
  2. delphi oracle新建用户,Delphi 中如何用另外一个用户的身份来运行一人程序
  3. anaconda如何更改环境配置_Anaconda环境配置2020-08-27
  4. FortiGate双链路不同运营商上网配置
  5. Perhaps you should add the directory containing libpcre.pc to the PKG_CONFIG_PATH
  6. java对象调用方法,java 对象调用
  7. 我的世界java出生蘑菇岛,《我的世界》出生就有蘑菇岛和海底神庙的地图,附近还有村庄!...
  8. [刘润五分钟商学院]-----工具类
  9. JavaScript基础知识总结(1)
  10. CMMB手机电视到了芯片企业创新的时侯
  11. 第三方支付接口搜集(附下载)
  12. 暂缓上市的云知声,技术究竟几何?
  13. 大数据血缘分析系统设计
  14. 【Oracle】ngrok 映射数据库地址为外网
  15. 在阿里 AI Lab 做 NLP 高级算法专家是一种什么样的体验?
  16. 精密光学测量1-概论
  17. CC2530定时器1使能
  18. 日本药妆店扫货必备手册·收藏版
  19. 从官网下载mysql 如何配置_从官网下载最新版Mysql并配置使用
  20. 俞敏洪在新东方年会发表演讲:2019,再次出发

热门文章

  1. web自动化测试—selenium游览器下拉框操作
  2. spring、springMvc、springBoot和springCloud的联系与区别
  3. python list 取重复次数
  4. java -Math类
  5. win8以上windows系统eclipse环境下图片显示乱码问题解决
  6. css sprint 生成工具 bg2css
  7. 看译飞的由浅入深漫谈margin属性
  8. 我做产品的三大思维:发散、纵横和表里(上)
  9. 爆料:当我们跟VC聊天时,他们都会问些什么?
  10. 【干货】美拍App是如何9个月做到用户过亿的