在Java中有多less有效数字有浮点数和双精度?
浮点数是否有32个二进制数字,而一个double是否有64个二进制数字? 文件太难理解了。
所有的位都翻译成有效数字吗? 或者小数点的位置占用了一些位?
float : 32位 (4字节),其中23位用于尾数(约7位十进制数字)。 8位用于指数,所以浮点数可以使用这8位将小数点“移动”到右侧或左侧。 这样做可以避免在尾数中存储大量的零,如0.0000003(3×10 -7 )或3000000(3×10 7 )。 有1位用作符号位。
double : 64位 (8字节),其中52位用于尾数(大约16位十进制数字)。 11位用于指数,1位是符号位。
由于我们使用的是二进制(只有0和1),当数字非零时,尾数中的一位隐含地为1(浮点数和双精度使用此技巧)。
此外,由于一切都是二进制(尾数和指数)转换为十进制数通常是不准确的。 像0.5,0.25,0.75,0.125这样的数字是精确存储的,但是0.1不是。 正如其他人所说,如果您需要精确地存储美分,请不要使用float或double,请使用int,long,BigInteger或BigDecimal。
资料来源:
http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
来自java规范 :
浮点types是float和double,它们在概念上与单精度32位和双精度64位格式的IEEE 754值和在IEEE标准中针对二进制浮点运算ANSI / IEEE标准754-1985(IEEE,纽约)。
由于在不了解IEEE754基础知识的情况下很难对数字进行任何操作,这里还有一个链接 。
理解精度不统一是很重要的,这不像整数那样精确地存储数字。
一个例子 :
double a = 0.3 - 0.1; System.out.println(a);
版画
0.19999999999999998
如果你需要任意精度(例如为了财务目的),你可能需要大十进制 。
一个正常的math答案。
理解浮点数被实现为表示指数和其余部分的一些比特,大部分用于数字(在二进制系统中),具有以下情形:
如果最低有效位被改变,则指数很高,例如10 23,两个相邻的可变数字之间会出现很大的差异。 此外,基数2的小数点使得许多基数10的数字只能近似; 1/5,1/10是无止境的数字。
所以一般来说 :如果你关心有效数字,不应该使用浮点数。 对于计算的金额,e,a,最好使用BigDecimal 。
对于物理浮点双打是足够的, 浮动几乎从来没有。 此外,处理器的浮点部分FPU甚至可以在内部使用更多的精确度。
浮点数使用指数forms编码,就像m * b ^ e
,即不像整数。 您提出的问题在定点数字的背景下将是有意义的。 有许多定点算术库可用。
关于浮点运算:小数位数取决于演示文稿和数字系统。 例如,有周期性数字( 0.33333
),它没有十进制的有限表示,但有一个在二进制中,反之亦然。
另外值得一提的是,直到某一点的浮点数确实有一个大于1的差值,即value + 1
产生value
,因为value + 1
不能用m * b ^ e
编码,其中m
, b
和e
是固定的长度。 对于小于1的值也是如此,即所有可能的码点不具有相同的距离。
正因为如此,像定点数字一样,没有精确的n
数字,因为不是每个具有n
十进制数字的数字都有IEEE编码。
有一个几乎是必须的文件,你应该阅读然后解释浮点数字: 每个计算机科学家应该知道的浮点运算 。
看看Float.intBitsToFloat
和Double.longBitsToDouble
,这些解释了位如何对应于浮点数。 特别是,正常的float
看起来像这样
s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW
其中A … W是23比特 – 0和1 – 表示二进制中的分数 – s是+/- 1,分别由0或1表示,exp是有符号的8比特整数。
如果我们看看最小正浮点值。
Float.MIN_VALUE = 1.4E-45f; // 0.000000000000000000000000000000000000000000001401298464324817
所以在技术上float可以保持60个值,因此对于(1和-1)之间的范围,你可能只想使用44个地方。
对于一般的目的,我喜欢留在9995.9995和-9995.9995之间,最低精度为0.0001。
为了好玩,你可以尝试:
System.out.println(new DecimalFormat("#####.#####").format(9996.9996f));
Result: 9997
如果我们看一下最小正双精度值。
Double.MIN_Value = 4.9E-324; // 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049
所以在技术上double可以容纳326个值,因此对于(1和-1)之间的范围,你可能只想使用324个地方。