### 概述
Java的Float类主要的作用就是对基本类型float进行封装,提供了一些处理float类型的方法,比如float到String类型的转换方法或String类型到float类型的转换方法,当然也包含与其他类型之间的转换方法
> java float类型用IEEE754标准规定;
float占用4个字节,包括:
* 1bit(符号位):0表示正数,1表示负数;
* 8bits(指数位):float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;
* 23bits(尾数位):实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 \[1,2),非规约浮点数的尾数部分范围在(0,1)
![](https://img.kancloud.cn/75/5c/755cd769c23a7d594431ce64cf46dea3_1302x250.png)
示例:
```
8.25 的 float 表示
整数8的二进制:1000
小数0.25的二进制:.01
8.25整体的二进制:1000.01 → 1.00001 * 2^3
小数点左移 3 位,所以指数部分(3 + 127) = 130,二进制是 10000010
尾数:去掉小数点前面的1,为 00001,补充到 23 位,000 0100 0000 0000 0000 0000
最终 8.25 在内存中存储的二进制是:0100 0001 0000 0100 0000 0000 0000 0000
```
```
9.5 的 float 表示
9.5的二进制:1001.1 -> 1.0011 * 2^3
指数位是 (3 + 127)=130,二进制 10000010
尾数是 0011 000000 0000000000 000
最终 9.5 在内存中存储的二进制是:010000010 0011 000000 0000000000 000,和程序打印出来的一致。
```
类继承关系:
```
public final class Float extends Number implements Comparable<Float> {
public static final float POSITIVE_INFINITY = 1.0f / 0.0f; // 正无穷大
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; // 负无穷大
public static final float NaN = 0.0f / 0.0f; // Not a Number(不是数)(输出就是NaN)
// 指数部分的最大值(指数位的长度1个字节):127,最小值为-126
public static final int MAX_EXPONENT = 127;
public static final int MIN_EXPONENT = -126;
// 一个float占4个字节(32位)
public static final int SIZE = 32;
}
```
> 说明:这是java的规定,没必要深究为什么1.0/0.0不报错,不过1/0肯定报错
#### 关于IEEE 754
> 在看Float前需要先了解IEEE 754标准,该标准定义了浮点数的格式还有一些特殊值,它规定了计算机中二进制与十进制浮点数转换的格式及方法。规定了四种表示浮点数值的方法,单精确度(32位)、双精确度(64位)、延伸单精确度(43位以上)与延伸双精确度(79位以上)。多数编程语言支持单精确度和双精确度,这里讨论的Float就是Java的单精确度的实现
## 类方法:
1.toString\(float f\):
```
public String toString() {
return Float.toString(value);
}
public static String toString(float f) {
return FloatingDecimal.toJavaFormatString(f);
}
```
> FloatingDecimal:的作用是将float格式化转换,即什么时候用数字显示\(位数小于8位\),什么时候用指数显示\(位数>=8位\)
> 更加详细的在API中有说明
2.toHexString\(float f\):转成16进制的字符串(用科学计数法表示)
```
public static String toHexString(float f) {
if (Math.abs(f) < FloatConsts.MIN_NORMAL
&& f != 0.0f ) {// float subnormal
// Adjust exponent to create subnormal double, then
// replace subnormal double exponent with subnormal float
// exponent
String s = Double.toHexString(Math.scalb((double)f,
/* -1022+126 */
DoubleConsts.MIN_EXPONENT-
FloatConsts.MIN_EXPONENT));
return s.replaceFirst("p-1022$", "p-126");
}
else // double string will be the same as float string
return Double.toHexString(f);
}
```
3.两个valueOf\(\):将字符串/浮点数转换成Float类型的对象
```
public static Float valueOf(String s) throws NumberFormatException {
return new Float(parseFloat(s));
}
public static Float valueOf(float f) {
return new Float(f);
}
```
4.parseFloat\(String s\):和valueOf重复了
```
public static float parseFloat(String s) throws NumberFormatException {
return FloatingDecimal.parseFloat(s);
}
```
5.isNaN\(float v\):判断是不是一个‘不是数’\(NaN和任何东西都不想等,包括他自己\)
```
public static boolean isNaN(float v) {
return (v != v);
}
```
6.isInfinite\(float v\):判断是不是正无穷或者负无穷(这两个数使计算没有任何意义)
```
public static boolean isInfinite(float v) {
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
}
```
7.floatToRawIntBits\(float value\) floatToIntBits\(float value\) intBitsToFloat\(int bits\):
> * 根据 IEEE 754 的浮点“单一形式”中的位布局,返回指定浮点值的表示形式
> * 根据 IEEE 754 的浮点“单一形式”中的位布局,返回指定浮点值的表示形式,并保留非数字 \(NaN\) 值。
> * 返回对应于给定的位表示形式的 float 值。该参数被认为是符合 IEEE 754 的浮点“单一形式”中的位布局规定的浮点值表示形式
```
public static native float intBitsToFloat(int bits);
public static native int floatToRawIntBits(float value);
public static int floatToIntBits(float value) {
int result = floatToRawIntBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & FloatConsts.EXP_BIT_MASK) ==
FloatConsts.EXP_BIT_MASK) &&
(result & FloatConsts.SIGNIF_BIT_MASK) != 0)
result = 0x7fc00000;
return result;
}
```
8.compare\(float f1, float f2\):比较两个float的大小
```
public static int compare(float f1, float f2) {
if (f1 < f2)
return -1; // Neither val is NaN, thisVal is smaller
if (f1 > f2)
return 1; // Neither val is NaN, thisVal is larger
// Cannot use floatToRawIntBits because of possibility of NaNs.
int thisBits = Float.floatToIntBits(f1);
int anotherBits = Float.floatToIntBits(f2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
```
### float二进制表示
```
int i = Float.floatToIntBits(8.25f);
System.out.println(Integer.toBinaryString(i)); // output==>1000001000001000000000000000000
```
### 精度损失
看下面的程序:
```
float f = 2.2f;
double d = (double) f;
System.out.println(f);
System.out.println(d);
```
打印出来的结果:
```
2.2
2.200000047683716
```
为什么会出现这种情况?
对于不能用二进制表示的 十进制小数,二进制小数位会进行循环,所以会损失精度。比如下面的语句会输出 true:
```
System.out.println(2.2f == 2.20000001f);
```
### 测试
```
float num = 4.0f / 0.0f;
System.err.println(num); // java中规定分母不能为0,但是浮点数计算中不抛异常
output==>Infinity
```
- java演变
- JDK各个版本的新特性
- JDK1.5新特性
- JDK1.6新特性
- JDK1.7新特性
- JDK1.8新特性
- JAVA基础
- 面向对象特性
- 多态
- 方法重载
- 方法重写
- class
- 常量
- 访问修饰符
- 类加载路径
- java-equals
- 局部类
- java-hashCode
- Java类初始化顺序
- java-clone方法
- JAVA对象实例化的方法
- 基础部分
- JAVA基础特性
- JAVA关键字
- javabean
- static
- 日期相关
- final
- interface
- 函数式接口
- JAVA异常
- 异常屏蔽
- try-with-resource资源泄露
- JAVA引用
- WeakReference
- SoftReference
- PhantomReference
- 位运算符
- try-with-resource语法糖
- JDK冷知识
- JAVA包装类
- JAVA基本类型与包装类
- java.lang.Boolean
- java.lang.Integer
- java.lang.Byte
- java.lang.Short
- java.lang.Long
- java.lang.Float
- java.lang.Double
- java.lang.Character
- 日期相关
- TemporalAdjusters
- String
- 字符串常量池
- String拼接
- String编译期优化
- StringBuilder&StringBuffer
- intern
- 注解
- java标准注解
- 内置注解
- 元注解
- 自定义注解
- 注解处理器
- JVM注解
- Java8 Annotation新特性
- 反射-Reflective
- Reflection
- Class
- Constructor
- Method
- javabean-property
- MethodHandles
- 泛型
- 类型擦除
- bridge-method
- Accessor&Mutator方法
- enum
- JAVA数组
- finalize方法
- JAR文件
- JAVA高级编程
- CORBA
- JMX
- SPI
- Java SPI使用约定
- ServiceLoader
- 实际应用
- IO
- 工具类
- JDK常用工具类
- Objects
- System
- Optional
- Throwable
- Collections
- Array
- Arrays
- System
- Unsafe
- Number
- ClassLoader
- Runtime
- Object
- Comparator
- VarHandle
- 数据结构
- 栈-Stack
- 队列(Queue)
- Deque
- PriorityQueue
- BlockingQueue
- SynchronousQueue
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
- ConcurrentLinkedQueue
- 列表
- 迭代器
- KV键值对数据类型
- HashMap
- TreeMap
- Hash冲突
- ConcurrentHashMap
- JDK1.7 ConcurrentHashMap结构
- jdk7&jdk8区别
- 集合
- Vector
- Stack
- HashSet
- TreeSet
- ArrayList
- LinkedList
- ArrayList && LinkedList相互转换
- 线程安全的集合类
- 集合类遍历性能
- 并发容器
- CopyOnWriteArrayList
- ConcurrentHashMap
- 同步容器
- BitMap
- BloomFilter
- SkipList
- 设计模式
- 设计模式六大原则
- 单例模式
- 代理模式
- 静态代理
- 动态代理
- JDK动态代理
- cglib动态代理
- spring aop
- 策略模式
- SpringAOP策略模式的运用
- 生产者消费者模式
- 迭代器模式
- 函数式编程
- 方法引用
- 性能问题
- Lambda
- Lambda类型检查
- Stream
- findFirst和findAny
- reduce
- 原始类型流特化
- 无限流
- 收集器
- 并行流
- AOP
- 静态织入
- aspect
- aspect的定义
- AspectJ与SpringAOP
- 动态织入
- 静态代理
- 动态代理
- JDK动态代理
- CGLib动态代理
- Spring AOP
- SpringAOP五种通知类型
- @Before
- @AfterReturning
- @AfterThrowing
- @After
- @Around
- Aspect优先级
- SpringAOP切点表达式
- within
- execution
- 嵌套调用
- 系统优化与重构
- 重叠构造器模式
- 工具类构造器优化
- 常见面试题
- new Object()到底占用几个字节
- 访问修饰符
- cloneable接口实现原理
- 异常分类以及处理机制
- wait和sleep的区别
- 数组在内存中如何分配
- 类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式
- 类的实例化顺序
- 附录
- JAVA术语
- FAQ
- 墨菲定律
- 康威定律
- 软件设计原则
- 阿姆达尔定律
- 字节码工具
- OSGI