讲述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) |
见图:
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.