Java中的浮点数剖析续(精)
- 格式:doc
- 大小:31.00 KB
- 文档页数:3
java 浮点类型与表示整数的整型不同,浮点型代表的是实数,其实就是包含小数点和小数点右边的数值部分。
简单的讲,浮点类型的数据,一般有整数、小数点和小数部分组成。
在Java程序中,浮点类型有float和double两种,分别代表单精度和双精度的数值。
它们的区别主要是所占用内存的大小不同。
●float型该类型在内存中分配4个字节,占32位,范围从10的-38次方到10的38次方和-10的38次方到-10的-38次方。
例如,“float x=123.456f ,y=2e20f;”定义x 和y的单精度类型。
在定义float型的数据末尾必须有f或F,以与double类型进行区别。
●double型该类型在内存中分配8个字节,范围从10的-308次方到10的308次方和-10的-308次方到-10的-308次方。
例如,“double x=1234567.98,y=8980.09d;”分别定义了x和y的双精度类型。
在定义double类型时,数字末尾须添加d或D。
双精度类型double比单精度类型float具有更高的精度和更大的表示范围,常常用于科学计算等高精度场合。
例如,sqlt()方法(由标准Math类定义)返回一个其double参数的平方根的double 值。
下面就是利用sqlt()方法,求两个参数和的平方根。
代码如下:执行上述代码,结果如图3-2所示。
关于本示例还有一点说明,sqrt()是标准Math类的一个成员。
注意调用sqrt()的方式,sqrt()跟在类名Math的后面。
这与System.out.println()的方式一样。
图3-2 输出平方根。
javafloat精度问题(有效位数)
范围是3.4E-38 ——3.4E+38,可提供7位有效数字。
上述这两个量都是近似值,各个编译器不太⼀样的。
这个⽐较复杂,建议你找⼀下IEEE754标准看⼀下。
这个简单说⼀下吧:
在IEEE754标准中进⾏了单精度浮点数(float)和双精度数浮点数(double)的定义。
float有32bit,double有64bit。
它们的构成包括符号位、指数位和尾数位。
这些位的构成如下:
种类-------符号位-------------指数位----------------尾数位----
float---第31位(占1bit)---第30-23位(占8bit)----第22-0位(占23bit)
double--第63位(占1bit)---第62-52位(占11bit)---第51-0位(占52bit)
取值范围主要看指数部分:
float的指数部分有8bit(2^8),由于是有符号型,所以得到对应的指数范围-128~128。
double的指数部分有11bit(2^11),由于是有符号型,所以得到对应的指数范围-1024~1024。
由于float的指数部分对应的指数范围为-128~128,所以取值范围为:
-2^128到2^128,约等于-3.4E38 — +3.4E38
精度(有效数字)主要看尾数位:
float的尾数位是23bit,对应7~8位⼗进制数,所以有效数字有的编译器是7位,也有的是8位。
java浮点数二进制Java浮点数在内存中的存储形式是用二进制表示的,这个表示方式由三部分组成:符号位、指数位和尾数位。
具体的二进制表示方式如下所述。
Java中的浮点数类型有两种:float和double,分别占用4个字节和8个字节的存储空间。
float类型的浮点数符号位占用1位,指数位占用8位,尾数位占用23位;而double类型的浮点数符号位占用1位,指数位占用11位,尾数位占用52位。
首先,浮点数的符号位用来表示浮点数的正负,0表示正数,1表示负数。
其次,指数位用来表示浮点数的数量级,即所谓的阶码。
指数位的范围是一个有符号的整数,可以表示的范围为-2^(n-1)到2^(n-1)-1,其中n表示指数位的位数。
对于float类型的浮点数,n为8,所以指数位可以表示的范围为-2^7到2^7-1;对于double类型的浮点数,n为11,所以指数位可以表示的范围为-2^10到2^10-1。
最后,尾数位用来表示浮点数的有效数字。
尾数位的长度决定了浮点数的精度,尾数位越长,浮点数的精度就越高。
float类型的浮点数尾数位长度为23,double类型的浮点数尾数位长度为52。
对于浮点数的具体的二进制表示方法,首先要将十进制数转换为二进制数。
转换时可以采用以下的步骤:1. 将十进制数的整数部分和小数部分分别转换为二进制数。
2. 对整数部分采用除2取余法,从低位到高位依次计算余数,并将余数排列成二进制数的低位。
3. 对小数部分采用乘2取整法,从高位到低位依次计算整数部分,并将整数部分排列成二进制数的高位。
例如,对于十进制数3.75的二进制表示,具体的步骤如下:1. 整数部分转换:3除以2,余数为1,所以最低位为1;1除以2,商为0,所以下一位为0。
2. 小数部分转换:0.75乘以2,整数部分为1,所以最高位为1;0.5乘以2,整数部分为1,所以下一位为1。
经过转换,得到的二进制表示为11.11。
在计算机中,浮点数还需要进行规格化操作,即将二进制表示进行标准化,使得指数位的值在表示范围内最大或最小。
程序员必知之浮点数运算原理详解程序员必知之浮点数运算原理详解 导读:浮点数运算是⼀个⾮常有技术含量的话题,不太容易掌握。
许多程序员都不清楚使⽤==操作符⽐较float/double类型的话到底出现什么问题。
许多⼈使⽤float/double进⾏货币计算时经常会犯错。
这篇⽂章是这⼀系列中的精华,所有的软件开发⼈员都应该读⼀下。
随着你经验的增长,你肯定想去深⼊了解⼀些常见的东西的细节,浮点数运算就是其中之⼀。
1. 什么是浮点数? 在计算机系统的发展过程中,曾经提出过多种⽅法表达实数。
【1】典型的⽐如相对于浮点数的定点数(Fixed Point Number)。
在这种表达⽅式中,⼩数点固定的位于实数所有数字中间的某个位置。
货币的表达就可以使⽤这种⽅式,⽐如 99.00 或者 00.99 可以⽤于表达具有四位精度(Precision),⼩数点后有两位的货币值。
由于⼩数点位置固定,所以可以直接⽤四位数值来表达相应的数值。
SQL 中的 NUMBER 数据类型就是利⽤定点数来定义的。
【2】还有⼀种提议的表达⽅式为有理数表达⽅式,即⽤两个整数的⽐值来表达实数。
定点数表达法的缺点在于其形式过于僵硬,固定的⼩数点位置决定了固定位数的整数部分和⼩数部分,不利于同时表达特别⼤的数或者特别⼩的数。
最终,绝⼤多数现代的计算机系统采纳了所谓的浮点数表达⽅式。
【3】浮点数表达⽅式,这种表达⽅式利⽤科学计数法来表达实数,即⽤⼀个尾数(Mantissa ),⼀个基数(Base),⼀个指数(Exponent)以及⼀个表⽰正负的符号来表达实数。
⽐如 123.45 ⽤⼗进制科学计数法可以表达为 1.2345 × 102 ,其中 1.2345 为尾数,10为基数,2 为指数。
浮点数利⽤指数达到了浮动⼩数点的效果,从⽽可以灵活地表达更⼤范围的实数。
提⽰: 尾数有时也称为有效数字(Significand)。
尾数实际上是有效数字的⾮正式说法。
Java浮点数存储格式JAVA中浮点数有两个基础类型:float和double。
float占据4个字节,double 占据8个字节。
下面将以float类型为例,介绍浮点数的存储方式。
double类型和float类型的存储方式雷同。
1.浮点数的存储方式浮点数的存储格式比较特殊,下图是4字节的float变量的存储示意图:根据IEEE754浮点数表示标准,一个float变量在存储中由三部分组成,分别是:符号位:1位(31),表示float的正负,0为正,1为负幂指数:8位(23-30),表示2进制权的幂次有效位:23位(0-22),表示有效数字2.浮点数的取值范围在float的存储中,有4个特殊的存储值,分别是:0x7f800000:正无穷大,Float.intBitsToFloat()打印显示为infinity0xff800000:负无穷大,打印显示为-infinity0x00000000:正零,打印显示为0.00x80000000:负零,打印显示为-0.0注意,在Java中,infinity!=-infinity,但是0.0==-0.0以上4个特殊存储值将float的存储分为4个段[0x00000001,0x7f7fffff]:正float数,共2^31-2^23-1个[0x7f800001,0x7fffffff]:非数字,打印显示NaN,共2^23-1[0x80000001,0xff7fffff]:负float数,共2^31-2^23-1个[0xff800001,0xffffffff]:非数字,打印显示NaN,共2^23-13.浮点数的格式转换令bits表示一个整数,其存储空间为4字节,下面我们求出这4个字节表示的float类型数字为多少。
int s = ((bits>>31) == 0)?1:-1; //取出1bit符号位int e = ((bits>>23) & 0xff); //取出8bit的幂指数//取出23位有效位int m = (e==0)?((bits & 0x7fffff) << 1):((bits & 0x7fffff) | 0x800000);则该存储空间表示的浮点数为 s*m*2^(e-150)分析:[0x00000001,0x007fffff]:相应实数范围为[(2^-149),(2^-126)-(2^-149)],即大约为[1.4E-45,1.2E-38],离散间隔固定为(2^-149)即约为1.4E-45,实数个数为2^23个。
java 浮点类型计算Java浮点类型计算浮点类型是Java中一种用于表示小数的数据类型,它可以存储具有小数部分的数字。
在Java中,有两种浮点类型:float和double。
一、float类型float类型是单精度浮点类型,它占用4个字节,可以表示大约6到7个有效数字。
在Java中,可以使用以下方式声明一个float类型的变量:float num = 3.14f;注意,在声明float类型变量时,需要在数字后面添加一个f或F作为后缀,表示这是一个float类型的数字。
float类型的计算包括基本的算术运算和一些常用的数学函数。
例如,可以对两个float类型的变量进行加减乘除运算,如下所示:float a = 3.14f;float b = 2.718f;float sum = a + b; // 加法float difference = a - b; // 减法float product = a * b; // 乘法float quotient = a / b; // 除法还可以使用Math类中的一些数学函数对float类型的变量进行计算,如下所示:float c = -3.14f;float absoluteValue = Math.abs(c); // 绝对值float squareRoot = Math.sqrt(a); // 平方根float power = Math.pow(a, 2); // 幂次运算二、double类型double类型是双精度浮点类型,它占用8个字节,可以表示大约15到16个有效数字。
在Java中,可以使用以下方式声明一个double类型的变量:double num = 3.14;与float类型类似,double类型的计算也包括基本的算术运算和一些常用的数学函数。
例如,可以对两个double类型的变量进行加减乘除运算,如下所示:double a = 3.14;double b = 2.718;double sum = a + b; // 加法double difference = a - b; // 减法double product = a * b; // 乘法double quotient = a / b; // 除法同样,可以使用Math类中的一些数学函数对double类型的变量进行计算,如下所示:double c = -3.14;double absoluteValue = Math.abs(c); // 绝对值double squareRoot = Math.sqrt(a); // 平方根double power = Math.pow(a, 2); // 幂次运算浮点类型的计算需要注意以下几点:1. 精度损失:由于浮点类型的表示方式是用有限的二进制位数来近似表示无限的小数,所以在进行浮点类型的计算时,可能会存在精度损失的问题。
java单精度浮点数定义Java是一种广泛使用的编程语言,它支持许多数据类型。
单精度浮点数是其中之一,它可以存储小数点后6-7位的数字。
在本文中,我们将讨论Java中单精度浮点数的定义及其使用方法。
一、定义单精度浮点数在Java中,单精度浮点数用关键字“float”来定义。
例如,下面的代码定义了一个名为“myFloat”的单精度浮点数,并将其初始化为3.14f:```float myFloat = 3.14f;```请注意,在赋值时,必须在数字末尾加上一个小写字母“f”,以显示这是一个单精度浮点数。
否则,编译器将默认将其视为双精度浮点数。
二、浮点数的精度单精度浮点数可以存储小数点后6-7位数字。
这是因为,它使用32位(4字节)来存储数字。
如果需要更高的精度,请使用双精度浮点数,它使用64位(8字节)存储数字。
双精度浮点数的定义如下:```double myDouble = 3.1415926;```三、使用单精度浮点数单精度浮点数可用于各种数学运算,例如加法、减法、乘法和除法。
下面的代码演示如何使用单精度浮点数进行加法运算:```float num1 = 5.5f;float num2 = 3.3f;float result = num1 + num2;System.out.println(result);```此代码输出结果为“8.8”。
需要注意的是,由于浮点数的精度有限,因此在进行比较时,应使用“epsilon”值来判断它们是否相等。
例如:```float num1 = 5.5f;float num2 = 5.500001f;float epsilon = 0.0001f;if(Math.abs(num1 - num2) < epsilon){System.out.println("num1 和 num2 是相等的");} else {System.out.println("num1 和 num2 不相等");}```此代码将输出“num1 和 num2 是相等的”。
java中float的用法
Java中的float是一种浮点型变量类型,用于表示小数,它占
用4个字节(32位),范围大约在-3.4E38到3.4E38之间。
float类型的变量在声明时需要在值后面加上f或F,以表示这
是一个float类型的值。
例如:
float num1 = 3.14f;
float num2 = 2.5F;
在使用float类型时,需要注意以下几点:
1. 小数点后至少要有一位数字,否则会被认为是double类型。
2. float类型的数字可以使用科学计数法表示,例如:
float num3 = 2.5e2f;
3. 在进行浮点数运算时,需要注意精度问题,因为浮点数运算
可能会产生四舍五入的误差。
例如:
float a = 0.1f;
float b = 0.2f;
float c = a + b;
System.out.println(c); // 输出结果为0.30000001192092896 4. 如果需要比较两个float类型的数字是否相等,不能直接使
用==运算符,而应该使用pare()方法或者Math.abs()方法。
例如:
float d = 0.1f;
float e = 0.1f;
if(pare(d,e) == 0){
System.out.println('d和e相等');
}
if(Math.abs(d-e) < 0.000001){
System.out.println('d和e相等');
}
以上就是Java中float类型的用法,希望对大家有所帮助。
Java中的float类型在进行运算时可能会出现精度丢失的问题,这是由于浮点数在计算机中的存储和表示方式导致的。
下面我们来详细解释java float小数丢失精度的原理。
浮点数表示方式
浮点数在计算机中是以二进制形式存储的,采用IEEE 754标准表示。
在这种表示方式下,浮点数由三部分组成:符号位、指数位和尾数位。
其中符号位表示正负号,指数位表示数值的指数部分,尾数位表示数值的有效数字部分。
二进制无法精确表示某些十进制数
由于浮点数是以二进制形式存储的,而我们通常使用的是十进制数,因此有些十进制数在二进制中是无法精确表示的。
例如,这个简单的十进制数在二进制中是一个无限循环小数。
精度丢失问题
当进行浮点数的运算时,由于二进制无法精确表示某些十进制数,可能会导致精度丢失的问题。
例如,当两个浮点数相加或相乘时,其结果可能会存在误差,这种误差就是由于浮点数的表示方式导致的。
解决方法
为了避免精度丢失的问题,可以使用BigDecimal类来进行精确的浮点数运算。
BigDecimal类提供了精确的数字运算功能,可以避免浮点数运算时的精度丢失问题。
总结
在Java中,float类型的小数可能会出现精度丢失的问题,这是由于浮点数在计算机中的存储和表示方式导致的。
为了避免这种问题,可以使用BigDecimal 类来进行精确的浮点数运算。
通过对浮点数表示方式和精度丢失问题的详细解释,我们可以更好地理解java float小数丢失精度的原理。
JAVA浮点数的范围和精度本篇先介绍IEEE754标准中针对浮点数的规范,然后以问答形式补充有关浮点数的知识点。
(⼀)IEEE754标准IEEE 754 标准即IEEE浮点数算术标准,由美国(IEEE)计算机学会旗下的微处理器标准委员会发布。
以32位float数据为例,在内存中的存储形式是1bit的符号位(S),8bit表⽰指数部分(Exp),23表⽰⼩数部分的尾数(Fraction)。
表⼀单精度浮点数在内存中存储形式1bit符号8bit指数部分23bit尾数符号位——S取0时表⽰负数,取1时表⽰负数。
指数部分——使⽤所谓的偏正值形式表⽰,⽽不是补码表⽰,即指数部分采⽤⼀个⽆符号的正数值存储。
也就是说指数部分要表⽰的值等于实际存储值减去⼀个固定值(对于单精度float类型,是127)。
采⽤这种⽅式表⽰的⽬的是简化⽐较,因为,如果采⽤补码表⽰的话,全体符号位S和Exp⾃⾝的符号位将导致不能简单的进⾏⼤⼩⽐较。
因为指数值的⼤⼩从0~255(0和255是特殊值),单精度的指数部分范围是-127~+128(对应的,-127和128是特殊值)。
尾数部分——23bit尾数仅能表⽰⼩数部分的尾数,部分由指数部分决定,具体见下表。
⼩数部分最⾼有效位是1的数被称为正规形式。
⼩数部分最⾼有效位是0的数被称为⾮正规形式,其他情况是特殊值。
表⼆单精度浮点数表⽰规则符号指数部分指数部分-127尾数部分⼩数部分的最⾼有效位形式1255128⾮0没有NaN12551280没有负⽆穷11~254-126~127任意1正规形式(负数)10-127⾮00⾮正规形式(负数)10-1270没有负000-1270没有正000-127⾮00⾮正规形式(正数)01~254-126~127任意1正规形式(正数)02551280没有正⽆穷0255128⾮0没有NaN按照IEEE标准,除了 NaN 以外,浮点数集合中的所有元素都是有序的。
如果把它们从⼩到⼤按顺序排列好,那顺序将会是:负⽆穷,正规形式(负数)、⾮正规形式(负数)、负0、正0、⾮正规形式(正数)、正规形式(正数)、正⽆穷。
Java中的浮点数剖析续Java中的浮点数剖析续文/BigBad...,浮点数的精度:单精度数的尾数用23位存储,加上默认的小数点前的1位1,2^(23+1)=16777216。
因为10^7<16777216<10^8,所以说单精度浮点数的有效位数(精度)是7位(即小数点后7位)。
双精度的尾数用52位存储,2^(52+1)=9007199254740992,10^16<9007199254740992<10^17,所以双精度的有效位数(精度)是16位(即小数点后16位)。
如果你在浮点数的有效位后增加数字的话,结果是不会变化的:Java代码System.out.println(1.67772156F);//1.6777215System.out.println(1.67772 150123456789D);//1.6777215012345679float取值范围:负数取值范围为-3.4028235E+38~-1.401298E-45,正数取值范围为1.401298E-45~3.4028235E+38。
Float.MIN_VALUE:保持float类型数据的最小正非零值的常量,最小正非零值为2^-149。
该常量等于十六进制的浮点文本0x0.000002P-126f,也等于Float.intBitsToFloat(0x1)=1.4e-45f。
(二进制为:0,00000000,00000000000000000000001)Float.MAX_VALUE:保持float类型的最大正有限大值的常量,最大正有限大值为(2-2^-23)*2^127。
该常量等于十六进制的浮点文本0x1.fffffeP+127f,也等于Float.intBitsToFloat(0x7f7fffff)=3.4028235e+38f。
(二进制为:0,11111110,11111111111111111111111)Java代码publicclassFloatTest{publicstaticvoidmain(String[]args){//只要指数为255,而尾数不为0时,该数不是一个数System.out.println(format(Integer.toBinaryString(0x7FC00000))+""+Floa t.intBitsToFloat(0x7FC00000));//NaNSystem.out.println(format(Integer. toBinaryString(0xFFC00000))+""+Float.intBitsToFloat(0xFFC00000));//Na NSystem.out.println(format(Integer.toBinaryString(0x7F800001))+""+Flo at.intBitsToFloat(0x7F800001));//NaN//指数为255,尾数为0时,该数就是无穷,符号位区分正无穷与负无穷System.out.println(format(Integer.toBinaryString(0x7F800000))+""+Floa t.intBitsToFloat(0x7F800000));//InfinitySystem.out.println(format(Int eger.toBinaryString(0xFF800000))+""+Float.intBitsToFloat(0xFF800000)) ;//Infinity//规定指数与尾数都为0时,规定结果就是0System.out.println(format(Integer.toBinaryString(0x0))+""+Float.intB itsToFloat(0x0));//正的最小float,趋近于0System.out.println(format(Integer.toBinaryString(0x1))+""+Float.intB itsToFloat(0x1));//1.4E-45//正的最大floatSystem.out.println(format(Integer.toBinaryString(0x7f7fffff))+"" +Float.intBitsToFloat(0x7f7fffff));//3.4028235E38//负的最大float,趋近于0System.out.println(format(Integer.toBinaryString(0x80000001))+""+Flo at.intBitsToFloat(0x80000001));//-1.4E-45//负的最小floatSystem.out.println(format(Integer.toBinaryString(0xFf7fffff))+"" +Float.intBitsToFloat(0xFf7fffff));//-3.4028235E38}privatestaticStringformat(Stringstr){StringBuffersb=newS tringBuffer(str);intsub=32-str.length();if(sub!=0){for(inti=0;i<sub;i++){sb.insert(0,0);}}sb.ins ert(1,"");sb.insert(10,"");returnsb.toString();}}2^-149=(0.00000000000000000000001)*2^-127=(00000000000000000000000.1)*2^-149=0x0.000002P-126f=0.000000000000000000000010*2^126(2-2^-23)*2^127=(10.00000000000000000000000-0.00000000000000000000001)*2^1270x1.fffffeP+127f=0x1.111111111111111111111110P+127double取值范围:负值取值范围-1.79769313486231570E+308~-4.94065645841246544E-324,正值取值范围为4.94065645841246544E-324~1.79769313486231570E+308。
Double.MIN_VALUE:保持double类型数据的最小正非零值的常量,最小正非零值为2^-1074。
它等于十六进制的浮点字面值0x0.0000000000001P-1022,也等于Double.longBitsToDouble(0x1L)。
Double.MAX_VALUE保持double类型的最大正有限值的常量,最大正有限值为(2-2^-52)*2^1023。
它等于十六进制的浮点字面值0x1.fffffffffffffP+1023,也等于Double.longBitsToDouble(0x7fefffffffffffffL)。
Java中的小数精确计算Java代码publicclassFloatCalc{//默认除法运算精度privatestaticfinalintDEF_DIV_SCALE=10;/***提供精确的加法运算。
*@paramv1被加数*@paramv2加数*@return两个参数的和*/publicstaticdoubleadd(doublev1,doublev2){BigDecimalb1=newBigDecimal (Double.toString(v1));BigDecimalb2=newBigDecimal(Double.toString(v2)) ;returnb1.add(b2).doubleValue();}/***提供精确的减法运算。
*@paramv1被减数*@paramv2减数*@return两个参数的差*/publicstaticdoublesub(doublev1,doublev2){BigDecimalb1=newBigDecimal (Double.toString(v1));BigDecimalb2=newBigDecimal(Double.toString(v2)) ;returnb1.subtract(b2).doubleValue();}/***提供精确的乘法运算。
*@paramv1被乘数*@paramv2乘数*@return两个参数的积*/publicstaticdoublemul(doublev1,doublev2){BigDecimalb1=newBigDecimal (Double.toString(v1));BigDecimalb2=newBigDecimal(Double.toString(v2)) ;returnb1.multiply(b2).doubleValue();}/***提供(相对)精确的除法运算,当发生除不尽的情况时,精确到*小数点以后10位,以后的数字四舍五入。
*@paramv1被除数*@paramv2除数*@return两个参数的商*/publicstaticdoublediv(doublev1,doublev2){returndiv(v1,v2,DEF_DIV_SC ALE);}/***提供(相对)精确的除法运算。
当发生除不尽的情况时,由scale参数指*定精度,以后的数字四舍五入。
*@paramv1被除数*@paramv2除数*@paramscale表示表示需要精确到小数点以后几位。
*@return两个参数的商*/publicstaticdoublediv(doublev1,doublev2,intscale){if(scale<0){throw newIllegalArgumentException("Thescalemustbeapositiveintegerorzero");} BigDecimalb1=newBigDecimal(Double.toString(v1));BigDecimalb2=newBigDe cimal(Double.toString(v2));returnb1.divide(b2,scale,BigDecimal.ROUND_ HALF_UP).doubleValue();}/***提供精确的小数位四舍五入处理。