java基础之float、double底层运算

目前java遵照IEEE制定的浮点数表示法来进行float,double运算。这种结构是一种科学计数法,用符号、指数和尾数来表示,底数定为2——即把一个浮点数表示为尾数乘以2的指数次方再添上符号。

我们来看一段java代码:

public class FloatToBinary {	public static void main(String[] args) {		float f1=8.5f;		System.out.println("f1底层数据(十进制):"+Float.floatToIntBits(f1));		int int1=Float.floatToIntBits(f1);		System.out.println("f1底层数据(二进制):"+Integer.toBinaryString(int1));	}}

打印结果:f1底层数据(十进制):1091043328f1底层数据(二进制):1000001000010000000000000000000

我们知道float与double分别在内存中占有32位和64位,见下:

符号位  阶码 尾数 长度
float 1 8 23 32
double 1 11 52 64

IEEE浮点数表示标准:

V = (-1)s×M×2E

 E = e-Bias

其中Bias表示偏移量,float的偏移量为Bias=2k-1-1=28-1-1=127,double的偏移量为Bias=210-1=1023

浮点数在计算机中存储时,按照二进制科学计数法拆分为三个部分:符号位、指数部分和尾数部分。如下图所示:

存储时,按照最高位存储符号位,次高位存储指数部分,低位存储尾数部分的次序存储。存储时的排列示意图如下:

 

float类型的内存分布如下图所示:

double类型的内存分布如下图所示:

编码规则

在实际存储时要对使用二进制科学计数法表示的浮点数值的符号位、指数部分和尾数部分进行编码处理。一般需要分为规约形式的浮点数、非规约形式的浮点数和特殊值三种类型进行编码。其编码前后处理如下图所示:

注:非规约浮点数主要用于扩大0值附近的浮点数表示范围,非规约浮点数的绝对值均小于规约浮点数的绝对值,即前者在实数轴上更靠近0,这样可以提高0附近的计算精度;一般C、C++中float和double的取值范围都是按照规约浮点数定义的,MSDN文档和相关教材也是这么说的,但部分编译器按照ANSI/IEEE Std 754-1985标准实现了非规约浮点数,本文末尾留有程序示例说明。

符号位:0表示正数,1表示负数;

指数部分: float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;

尾数部分:实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 [1,2),非规约浮点数的尾数部分范围在(0,1)。

上面的理论在哪里都能看到,这只是IEEE754的定义而已,我们来实际用一下它是怎么表达小数的:

①求单精度8.5f 的二进制 过程。

首先8.5是正数所以符号位为0;

然后化为二进制,1*2^3+0*2^2+0*2^1+0*2^0 (整数部分)  . (小数点)   1*2^-1小数部分简化为1000.1

要把二进制数变成(1.f)*2^(exponent)的形式,其中exponent是指数即1.0001*2^3.

然后我们得到阶码为e=3+127=130 即阶码表示二进制为10000010.

余下小数0001,我们补齐至23位即00010000000000000000000。

这样符合结构 符号位   0   阶码 10000010 尾数00010000000000000000000

然后我们来看一下8.5存储在内存中01000001000010000000000000000000

因为java.lang.Integer.toBinaryString() 方法返回一个字符串表示的整数参数,以2为底的无符号整数,所以在开始的程序打印结果我们添加一个0,与我们算出的结果就相同了。

网上有很多关于float、double的转换解说,这里只是我涉及到了这块,然后自己去学习了一下,其实刚开始我看理论知识比较晕,后来看到别人以列子详细解说,然后再回头看理论,就发现也没那么难了。

时间: 2024-11-18 09:10:51

java基础之float、double底层运算的相关文章

java基础入门-float四舍五入保留两位小数注意的地方

float四舍五入保留两位小数注意的地方 最近在codewars做了一道非常简单的题目,但是它却花了我20来分钟,虽然最后解决了,但是中间发觉对于java的基础实在不行,回去要好好补一下 不说这么多,上题目:就是写一个方法,把英里每加仑换算成公里每升,保留两位数 一开始写的时候是没有问题,问题出现在保留两位数那里,我上一个测试代码 import java.util.regex.Pattern; public class Test { /* * 判断是否为整数 * * @param str 传入的

【Java基础】基本类型与运算【重要】

0.   Java基本数据类型 Java的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long.int.short.char和 byte,位运算符具体如下表: 运算符 说明 << 左移位,在低位处补0 >> 右移位,若为正数则高位补0,若为负数则高位补1 >>> 无符号右移位,无论正负都在高位补0 & 与(AND),对两个整型操作数中对应位执行布尔代数,两个位都为1时输出1,否则0. | 或(OR),对两个整型操

Java基础之二进制的位运算介绍

前言 Java编程思想中的操作符这个章节的第一句:在最底层,Java中的数据是通过使用操作符来做的.下面我将重点介绍位运算. 算术运算 Java语言中的基本算术操作符与其他的大多数的程序设计语言是相同的.其中包括 1.加,+ 2.减,- 3.乘,* 4.除,/ 5.取模, % 位运算 1.与 & 2.或 | 3.非 ~ 4.异或 ^ 5.左移 << 6.右移 >> 7.补零右移 >>> 参考资料 Java基本运算符 :https://www.cnblogs

java基础:字符数据参与运算

System.out.println('a'); . 输出结果:a System.out.println('a'+1); 输出结果 98 System.out.println("hello"+'a'+1); 输出结果: helloa97 字符串数据和其他数据做+,结果是字符串类型. 这里的+不是加法运算,而是字符串连接符. System.out.println('a'+1+"hello"); 输出结果:98hello System.out.println("

java基础学习-变量&运算

package com.J; public class java { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub float a=1.11111111111111f;    // 数据表示单精度末尾+"f",此处数据存储要溢出 double b=1.1111111111111111;  // java里面默认小数都为double双精度浮点

java中int,float,long,double取值范围,内存泄露

java中int,float,long,double取值范围是多少? 写道 public class TestOutOfBound { public static void main(String[] args) { System.out.println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //内存溢出System.out.println(Integer.MAX_VALUE); //2的31次方-1,10个数位,正的20亿左右,用在钱上面不一定够Sy

解决java float double 浮点型参与计算失精度

本人前段时间做一个社区电商应用,发现了一个 天坑   ...................让我哭会 . 下面听听我的踩坑之路吧 ,电商肯定跟¥打交道了,计算少不了的.由于本人太菜 单纯的以为  float  double 可以直接参与加减乘除 感觉这种代码万无一失没去想这么多直接 float*int . 之前简单测试没问题,项目上线后自己偶然才发现的(不知道公司测试干嘛的) ,当选择多件商品时 , 还是直接说现象吧 比如 在代码中    0.1 f  * A         A为int 型  

Java基础东西(按位操作运算)

http://aokunsang.iteye.com/blog/615658 前奏:   昨天一哥们问我Java位移你会吗,我说不会,想想位移这么麻烦,一般有位移的Java代码一律不看,有几个人会啊,是吧?但是那哥们的回答,让我郁闷半天:"这都不会啊,都是Java基础的东西呀!"我靠,我晕倒,听着老不爽了,so我决定对位移一探究竟,原来也这么随意啊,哈哈.因此,把心得总结如下,欢迎收看. 在这里先感谢一下,JavaEye上的高手们的技术博客指点.TKS very much. 技术总结:

关于Java中用Double型运算时精度丢失的问题

注:转自 https://blog.csdn.net/bleach_kids/article/details/49129943 在使用Java,double 进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1. 特别在实际项目中,通过一个公式校验该值是否大于0,如果大于0我们会做一件事情,小于0我们又处理其他事情. 这样的情况通过double计算出来的结果去和0比较大小,尤其是有小数点的时候,经常会因为精度丢失而导致程序处理流程出错. BigDecimal在<Eff