讲述float这个类型确实让我有点没有头绪,但还是简单说下。 

关于最大值最小值问题

Float.MAX_VALUE = 0x1.fffffeP+127f;

Float.MIN_VALUE = 2-149; 

ps:(看到MAX_VALUE这样令人发指的写法确实有些不爽,特地写出来就是想说明一下:

先看表达式:

   1. 0x代表 16进制

   2. 1.fffffe(不区分大小写) 代表16进制的小数表示,转换10进制需要 除以16

   3. p/P(不区分大小写) 代表2

   4. +/-  在这表代表的是指数符号  +127代表127次方,+号可以省略

   5. 最后一位f 代表转成float,而不是double 

对jvm,0x0.5 显然是不能接受的行为,但现在可以这样 0x0.5p0f, 这会是什么呢?

不妨灵活运用这种方式。) 

 

除了MAX_VALUE 和 MIN_VALUE 以外,我们发现:

MAX_EXPONENT = 127 有限 float 变量可能具有的最大指数。

MIN_EXPONENT = -126 标准化 float 变量可能具有的最小指数。

MIN_NORMAL = 0x1.0p-126f 保存 float 类型数据的最小正标准值的常量,即 2-126。

 

这时我们来看一个概念(当然我尽可能简单说):IEEE 754

1. IEEE二进制浮点数算术标准(IEEE 754)1980年代以来最广泛使用的浮点数运算标准。

2. IEEE 754规定了四种表示浮点数值的方式:单精确度(32位元)、双精确度(64位元)、延伸单精确度(43位元以上,很少使用)与延伸双精确度(79位元以上,通常以80位元实做)。只有32位元模式有强制要求,其他都是选择性的。(就是说我们的float)

3.

1 8 23 位长
S Exp Fraction
31 30至23

偏正值 (实际的指数大小+127)

22至0位编号(从右边开始为0)

见图:

490px-General_floating_point_frac_svg 

4.

单精度浮点数各种极值情况:

类别 正负号 实际指数 有偏移指数 指数域 尾数域 数值
0 -127 0 0000 0000 000 0000 0000 0000 0000 0000 0.0
负零 1 -127 0 0000 0000 000 0000 0000 0000 0000 0000 -0.0
1 0 0 127 0111 1111 000 0000 0000 0000 0000 0000 1.0
-1 1 0 127 0111 1111 000 0000 0000 0000 0000 0000 -1.0
最小的非规约数 * -126 0 0000 0000 000 0000 0000 0000 0000 0001 ±2−23 × 2−126 = ±2−149 ≈ ±1.4×10-45
中间大小的非规约数 * -126 0 0000 0000 100 0000 0000 0000 0000 0000 ±2−1 × 2−126 = ±2−127 ≈ ±5.88×10-39
最大的非规约数 * -126 0 0000 0000 111 1111 1111 1111 1111 1111 ±(1−2−23) × 2−126 ≈ ±1.18×10-38
最小的规约数 * -126 1 0000 0001 000 0000 0000 0000 0000 0000 ±2−126 ≈ ±1.18×10-38
最大的规约数 * 127 254 1111 1110 111 1111 1111 1111 1111 1111 ±(2−2−23) × 2127 ≈ ±3.4×1038
正无穷 0 128 255 1111 1111 000 0000 0000 0000 0000 0000 +∞
负无穷 1 128 255 1111 1111 000 0000 0000 0000 0000 0000 -∞
NaN * 128 255 1111 1111 non zero NaN
* 符号位可以为0或1 .

 

一下子搞出这么多东西可能会吓到你,那我用我的表述:

float和double 与以前你看到的int的二级制不再一样。 他把32位分成了3个段,当然根据某个标准(或者叫协议,比如IEEE754)。然后,为了应付这一切带来的琐碎事情,我们不得不建立更多的属性和方法。

 

当然,对IEEE754的表述显然并不满意,我决定单独写一篇附加说明,来说明它。

 

下面,看下 int f = 1 ,(特地用int,并不推荐此行为),跟我做如下事情:

int intValue = Float.floatToIntBits(i);
String binaryS = Integer.toBinaryString(intValue);
System.out.println("intValue = "+intValue);
System.out.println("binaryS = " + binaryS );
System.out.println(binaryS.length());
out:
intValue = 1065353216
binaryS = 111111100000000000000000000000
30

30位,说明第32位(即左数第一位)是0,31位是0。正如IEEE754中介绍的,第4条 value等于1时。

 

下面介绍下方法:

method: floatToIntBits(float value)

API这样描述:
     根据 IEEE 754 浮点“单一格式”位布局,返回指定浮点值的表示形式。
     我通俗的说:得到浮点值的二进制格式(<=32位),并以int的10进制返回。如果遇到这样的一个int值,可以通过intBitsToFloat(int)得到浮点值。
     此方法比floatToRawIntBits 多做一步,将 NaN 编码为一个“规范”NaN 值的位模式。

 

method:floatToRawIntBits(float value)
根据 IEEE 754 浮点“单一格式”位布局,返回指定浮点值的表示形式,并保留非数字 (NaN) 值。 

method:isInfinite() -还有个static方法,一起说明.
如果此 Float 值的大小是无穷大,则返回 true,否则返回 false。
见example:
 

 System.out.println(new Float(1/0.0f).isInfinite());
 System.out.println(Float.isInfinite(Float.NEGATIVE_INFINITY));
 System.out.println(iob1.isInfinite());
 System.out.println(Float.isInfinite(iob1));

 

method:hashCode()
调用 floatToIntBits(value); 

method:compareTo()
比较value 调用了compare 

method:compare(float f1,float f2)  static
见example:

 float iob1 = 9;// 需要加f强转吗?
 System.out.println(Float.compare(-9, iob1)); 
 System.out.println(Float.compare(Float.NaN, iob1)); 
 System.out.println(Float.compare(-(1.0f/0.0f), iob1));

 method:toString
调用了valueof 

method:toString(float f) static
用了getChars,new String(...)

 
依然做个小结:
1.  float 用起来简单,感谢jvm以及其所有开发人员
2.  float 用起来要慎重,他并非如int那样安全
举个例子:

 
 float basicf = 0.95f; 
 for(int i =100;i<=120;i++) {
  float f = i/100.0f
  System.out.println("f = "f+"----"+(f+basicf)); 
 } 


3.  Float有了正无穷大,负无穷大的概念
4.  float那些表现方式,以及jvm会在任何可能的地方将浮点变成double.