java浮点数储存

面试题:

public class FloatDouble {
 
	public static void main(String[] args) {
 
		float f_v1 = 20;  
		float f_v2 = 20.3f;  
		float f_v3 = 20.5f;  
		      
		double d_v1 = 20;  
		double d_v2 = 20.3;  
		double d_v3 = 20.5;
		
		System.out.println((f_v1 == d_v1)?"true":"false"); 
		System.out.println(f_v2 == d_v2?"true":"false");  
		System.out.println(f_v3 == d_v3?"true":"false");
		
	}
}

运行结果会是怎样的呢?, 解释运行结果的原因

这里涉及到浮点数是如何存储的.

  1. 如何将十进制转换成二进制浮点数呢, 先介绍一下十进制的浮点数 转换二进制的浮点数

分为两部分:

  1. 先将整数部分转换为二进制,

  2. 将小数部分转换为二进制, 然后将整数部分与小数部分相加。

以 20.5 转换为例,

20转换后变为 10100
0.5 要转换二进制,需要乘2, 乘完之后取整数部分,然后用乘的结果减去整数部分, 然后接着乘2, 直至最后没有小数或者小数出现循环, 即乘完.

如果等于0, 就取前面不为0的部分.

0.5 * 2 = 1.0 (取1)

0 * 2 = 0 (0)

所以, 转换后 0.5 = 0.1,

所以 20.5 转换二进制后, 20.5 = 10100.1(二进制)


再看一个浮点数 20.3

20 = 10100 (二进制)

0.3 * 2= 0.6 (0)

0.6 * 2 = 1.2 (1)

0.2 * 2= 0.4 (0)

0.4 * 2 = 0.8 (0)

0.8 *2 = 1.6 (1)

计算到这里, 将再出现0.6,进入循环了,所以,结果

0.3 = 0.010011001…1001

所以20.3 = 10100.010011001…1001 (二进制).

2.如果要把十进制浮点数,存储到内存空间中,也就是4个字节中,首先要把浮点数转换成二进制的浮点数, 然后再转换成科学计数法.

这里 20.5 = 10100.1(二进制) = 1.01001E4(十进制科学计数) = 1.01001E100(二进制科学计数), 这里E100指2的100次方

在java中,float 类型 数,占4个字节, 存储结构如下

             符号位:   1

             指数位:   8

             尾数位:   23,  如下图所示

           double 类型数,  占8个字节, 存储结构如下

             符号位:1

             指数位:11

             尾数位: 52

存储数据是一个萝卜一个坑, 首先存储符号位, 然后是 指数,最后尾数

比如20.5 = 1.01001E100(二进制)

这里使用到移位存储, 对于float 数值来说, 指数位要加上127, 即0111111(二进制)

00000100

+01111111


1000 0011

对于double 数值来说, 指数位要加上1023, 即0111 111 1111(二进制)

0000 000 0100

  • 0111 111 1111

1000 000 0011

所以20.5 存储的数值 是 (float): 0-10000011-01001 00000 00000 00000 000

(double):0-10000000011-01001+(47个0)
这里尾数位需要52位

现在看到20.5 转换为float, double 的二进制数, 指数和尾数是不同的, 注意,比较指数时 float 型会-127, double型 会-1023,因此

float 型又变成了00000100

double型又变成0000000100 ,这时候比较,因为两个指数的位数不同,一个8位,一个10位,8位的数会在前面自动补0

比较尾数时,float型数会自动在后面补0直至与double 型相同的52位

同理20.3 存储的数值 是: (float) 0-10000011-01001 10010 10011 00101 001

(double)0-1000000011-01001(后面循环1001, 直至尾数为52位)

与20.5的比较相似, 20.3的float型二进制和double型二进制,符号位与指数位都相同, 但是尾数位不相同,float型到了23位之后都是0, double型一直1001循环到52位. 这就是float型与double型比较之后不相等的原因
在这里插入图片描述
如果要将三个比较结果 都为true, 需在d_v2加上 (float), 也就是将double强制转为float型

<think>好的,我现在需要回答用户关于Java浮点数的问题,包括使用方法、数据类型、表示范围以及精度问题。首先,我得回忆一下Java浮点数的基本知识,然后结合提供的引用内容来组织回答。 首先,用户提到的数据类型主要是float和double,根据引用[1],float是单精度,占4字节,而double是双精度,占8字节。需要说明它们的内存占用和精度差异。引用[2]也提到尽可能使用更高精度的double,所以应该强调在大多数情况下推荐使用double,除非内存特别紧张。 接下来是表示范围。根据引用[4],可能需要具体数值。记得float的范围大约是±3.4e38,而double是±1.7e308。这部分需要准确,可能需要查阅标准,但根据引用里的内容,用户提供的引用可能没有具体数值,但根据常识,应该正确。 然后是使用方法。需要提到如何声明变量,比如float f = 1.23f,必须加f后缀,否则会被当作double。而double可以不用。同时,初始化、运算时的注意事项,比如自动类型转换的问题。引用[4]提到自动转换时是否丢失精度,比如将整型赋给float变量时,可能不会丢失,但大整数可能会有精度问题。例如,将一个大long值转换为float可能会损失精度,因为float的有效数字只有7位左右。 精度问题方面,引用[2]和[3]都提到了精度丢失的问题。比如引用[3]中的例子,用BigDecimal构造double值时出现的精度问题,说明浮点数无法精确表示某些十进制数。需要解释为什么会出现这种情况,比如二进制表示的问题,以及如何避免,如使用BigDecimal类,尤其是金融计算时。引用[2]建议使用BigDecimal,并注意构造方法应该用字符串而非直接传入double值,避免初始误差。 此外,引用[2]还提到算法设计以减少误差累积,可能需要在回答中提到一些最佳实践,比如避免大量连续运算,或者使用整数运算代替。 现在需要组织这些信息,结构要清晰。可能分成几个部分:数据类型(float和double的定义、内存、精度)、表示范围、使用方法(声明、赋值、运算)、精度问题及解决方案。最后生成相关问题。 在回答过程中,需要确保LaTeX格式正确,行内公式用$...$,独立公式用$$...$$。例如,表示范围时,可以用$$3.4 \times 10^{38}$$这样的格式。同时,引用标记要正确添加,比如在提到精度问题时引用[^3]的例子。 需要检查是否有遗漏的内容,比如是否覆盖了用户问题的所有方面:使用方法、数据类型、表示范围、精度问题。确保每个部分都有对应的引用支持,并正确标注来源。 最后生成相关问题,可能涉及如何选择float和double,BigDecimal的具体用法,精度问题的案例,以及优化建议等。</think>### Java浮点数详解 #### 一、数据类型与特点 Java提供两种浮点类型: - **`float`(单精度)**:占4字节,有效位数约7位,声明时需添加后缀`f`,例如:$f = 3.14\text{f}$[^1]。 - **`double`(双精度)**:占8字节,有效位数约15位,默认浮点类型,例如:$d = 9.8$。 #### 二、表示范围 - **`float`范围**:$$ \pm 3.4 \times 10^{38} $$ - **`double`范围**:$$ \pm 1.7 \times 10^{308} $$ 大整数赋值给`float`可能导致精度丢失,例如:$123456789$转换为`float`可能近似为$1.2345679 \times 10^8$[^4]。 #### 三、使用方法 1. **变量声明与初始化** ```java float f = 1.23f; // 必须加f后缀 double d = 4.56; // 默认double ``` 2. **运算注意事项** - 混合类型运算时,结果自动提升为`double`。 - 避免直接比较浮点数(例如:`0.1 + 0.2 == 0.3`返回`false`)。 #### 四、精度问题与解决方案 1. **精度丢失原因** 浮点数采用二进制存储,无法精确表示某些十进制小数(如$0.1$),导致舍入误差[^3]。 ```java System.out.println(0.1 + 0.2); // 输出0.30000000000000004 ``` 2. **解决方案** - **使用`BigDecimal`**:通过字符串构造避免初始误差[^2]。 ```java BigDecimal x = new BigDecimal("9.8"); // 精确表示 ``` - **算法优化**:减少连续运算次数,或用整数代替浮点数(例如:用“分”代替“元”)。 #### 五、应用场景建议 - **优先选择`double`**:除非内存敏感场景(如大规模数组)。 - **金融计算**:必须使用`BigDecimal`类。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值