Java中浮点数的基础知识
偶然查看Math.round的JDK
public static int round(float a) {
if (a != 0x1.fffffep-2f) // greatest float value less than 0.5
return (int)floor(a + 0.5f);
else
return 0;
}
注释说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.5
return (long)floor(a + 0.5d);
else
return 0;
}
查看JDK,果不其然,说明我的分析是没有问题的。
(以上基础知识来自《深入理解计算机系统》2.4.2)
Java中浮点数的基础知识的更多相关文章
- Java中的NIO基础知识
上一篇介绍了五种NIO模型,本篇将介绍Java中的NIO类库,为学习netty做好铺垫 Java NIO 由3个核心组成,分别是Channels,Buffers,Selectors.本文主要介绍着三个 ...
- java中浮点数的比较(double, float)(转)
问题的提出:如果我们编译运行下面这个程序会看到什么? public static void main(String args[]){ System.out.println(0.05+0.01); Sy ...
- 第87节:Java中的Bootstrap基础与SQL入门
第87节:Java中的Bootstrap基础与SQL入门 前言复习 什么是JQ? : write less do more 写更少的代码,做更多的事 找出所有兄弟: $("div" ...
- 第90节:Java中的Linux基础
第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686 MYSQL依赖包: yum -y install libaio.so ...
- 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承
<Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...
- ASP.NET中的C#基础知识
ASP.NET中的C#基础知识 说明:asp.net作为一种开发框架现在已经广为应用,其开发的基础除了前端的html.css.JavaScript等后端最重要的语言支持还是C#,下面将主要用到的基础知 ...
- MySQL中索引的基础知识
本文是关于MySQL中索引的基础知识.主要讲了索引的意义与原理.创建与删除的操作.并未涉及到索引的数据结构.高性能策略等. 一.概述 1.索引的意义:用于提高数据库检索数据的效率,提高数据库性能. 数 ...
- 计算价格, java中浮点数精度丢失的解决方案
计算价格, java中浮点数精度丢失的解决方案
- day29—JavaScript中DOM的基础知识应用
转行学开发,代码100天——2018-04-14 JavaScript中DOM操作基础知识即对DOM元素进行增删改操作.主要表现与HTML元素的操作,以及对CSS样式的操作.其主要应用知识如下图: 通 ...
随机推荐
- Perl多进程
perl作为一种解释性的语言,非常受广大系统管理员的欢迎,优点么就不多说了,坏处也有不少,比如对线程的支持,就一直不咋地,所以大多数情况下,我们都须要多个进程,来帮助我们完毕工作,闲话少说,上代码. ...
- 关于AS3的垃圾回收
FlashPlayer运行GC(Gabage Collection)的时间并不固定,它会根据你的内存的占用情况来决定运行GC的时间.它会根据用户机器的内存值来设定一个阀值,然后将程序的占用内存量保存在 ...
- mybatis0209 二级缓存
.1二级缓存 1.1.1原理 mybatis和spring整合后一级缓存就没有了,sqlSession在不关闭的前提下2次查询就会从缓存中取,一级缓存缓存在sqlSession对象里面,当多用户查询的 ...
- Java多线程中start()和run()的区别
Java的线程是通过java.lang.Thread类来实现的.VM启动时会有一个由主方法所定义的线程.可以通过创建Thread的实例来创建新的线程.每个线程都是通过某个特定Thread对象所对应的方 ...
- Python学习 之 匿名函数
1.匿名函数(lambda函数):lambda函数是一种快速定义单行的最小函数,是从Lisp借用来的,可以用在任何需要函数的地方. 普通函数定义如下: def f(x,y): return x*yf( ...
- C语言的ANSI/ISO标准
摘自:http://see.xidian.edu.cn/cpp/html/1658.html 从技术上讲有两种C语言标准,一种来自ANSI(American National Standard Ins ...
- python首次尝试——hello world
百忙之中抽空学习python,但是令人惊讶的是连hello world都写不出来.
- (转)Windows7 64位系统搭建Cocos2d-x 2.2.1最新版以及Android交叉编译环境(详细教程) .
声明:本教程在参考了以下博文,并经过自己的摸索后实际操作得出,本教程系本人原创,由于升级后的cocos2d-x有了一些变化,目前的博文还没有关于Cocos2d-x 2.2.1最新版搭建Android交 ...
- HFile解析 基于0.96
什么是HFile HBase.BigTable以及其他分布式存储.查询系统的底层存储都采用SStable的思想,HBase的底层存储是HFile,他要解决的问题就是如果将内容存储到磁盘,以及如何高效的 ...
- hive-初看hive
网上搜了一下找了很多介绍hive的资料,不是官方翻译就是含糊描述,对于刚接触的很难直观认识 我从一本介绍hadoop的书里找到了一些hive的资料,没太多废话.可以看看 http://pan.baid ...