IEEE-754 Floating-Point Conversion

来源:互联网 发布:数据库需求分析 编辑:程序博客网 时间:2024/06/10 03:35

本是问一朋友关于Java与C/C++中浮点小数的表示的问题,没想到他好好的写了一篇blog来回答我的问题。呵呵,真的谢谢slimzhao(一笑)。

看了他的blog学到了很多,现再引用并总结一下,同时为了记忆。

浮点数格式中的各个部分:
对于float:共32个bits,Bit 31是MSB(Most Significant Bit),Bit 0是LSB(Least Significant Bit),则
Bit 31是符号位,接下来的8位是指数位,指数位被视为一个无符号的数,它与127的差就是以2为底的指数的部分。 最后的23位是小数部分。
 而小数部分是这样规定的:
11001100110011001100110
这是0.9f 的小数部分,共23位,它表示:
1.11001100110011001100110
这样一个以2为基数的小数,小数点前面的1是隐含的,这是一个小技巧以获得额外的一位表示。所以上面的整个数是:
1 + (1/2+1/4) + (1/32+1/64) + (1/512+1/1024) + 1/(1024*8)+1/(1024*16) + 1/(1024*16*8)+1/(1024*16*16)
上面这个式子可以直接COPY到windows的计算器中,但注意复制完后要按一下“=”。不然还有一个运算没有进行。
它的结果是 1.7999999523162841796875,加上前面的指数部分值为-1((001111110)2 = (126)10; 126 - 127 = -1),效果也就是除以2,得到的值就是
0.89999997615814208984375。
数一数小数点后面的数字长度,是23位。把printf的输入精度也调整到这么多小数点:
printf("%.23f/n", 2.0f - 1.1f );
得到
0.89999997615814209000000
最后的7位与理论上可以得到的最精确结果不符,这是因为ANSI C标准中printf对其精度有一个上限。

至此可以知道C/C++语言对浮点数的内部表示是因为printf的精度要求没有指定,默认的精度是小数点后6位,后面的进行四舍五入处理,所以结果就是0.9了。在JAVA SE 5.0后加入了printf();函数,其效果和C中一样,四舍五入处理。
但Java的println可以从jdkapi中看到(Double.toString(double))
(对“而java的println 在Java之前并没有任何标准需要遵循, 所以它可以自作主张地把默认精度搞大一点”的一点补充)

toString

public static String toString(double d)
返回 double 参数的字符串表示形式。下面提到的所有字符都是 ASCII 字符。
  • 如果参数为 NaN,则结果是字符串 "NaN"。
  • 否则,结果是表示参数的符号和大小(绝对值)的字符串。如果符号为负,则结果的第一个字符是 '-' ('/u002D');如果符号为正,则结果中不显示符号字符。至于大小值 m
    • 如果 m 为无穷大,则用字符 "Infinity" 表示它;因此,正无穷大产生的结果就是 "Infinity",而负无穷大产生的结果是 "-Infinity"
    • 如果 m 为零,则用字符 "0.0" 表示它;因此,负零产生的结果是 "-0.0",而正零产生的结果是 "0.0"
    • 如果 m 大于或者等于 10-3,但小于 107,则采用不带前导零的十进制形式,用 m 的整数部分表示它,后面跟着 '.' ('/u002E'),再后面是表示 m 的小数部分的一个或多个十进制位数。
    • 如果 m 小于 10-3 或者大于或等于 107,则用所谓的“计算机科学记数法”表示它。让 n 成为满足 10n <= m < 10n+1 的惟一整数;然后让 a 成为 m 的精确算术商数值,并用 10n 这种形式表示它,因此,1 <= a < 10。然后,用 a 的整数部分表示大小值,它的表示形式为:一个十进制位数,后面跟着 '.' ('_apos;),接着是表示 a 的小数部分的十进制位数,再后面是字母 'E' ('-pos;),最后是用十进制整数形式表示的 n,这与通过方法 Integer.toString(int) 产生的结果非常相似。
必须为 ma 的小数部分显示多少位呢?至少必须有一位数来表示小数部分,除此之外,需要很多(但只能和需要的一样多)位数来惟一地区别参数值和 double 类型的邻近值。换句话说,假设 x 是用十进制表示法表示的精确算术值,是通过用于有限非零参数 d 的方法生成的。那么 d 必须是最接近 xdouble;如果两个 double 值都同样接近 x,那么 d 必须是其中之一,并且 d 的最低有效位必须是 0

使用NumberFormat 的子类创建浮点值的本地化字符串表示形式。

 

参数:
d - 要转换的 double 值。
返回:
参数的字符串表示形式。

这回我的思考也想告诉大家,看jdk时要多查几下,不要就止于PrintStream.println(double d)了。再看看
print(dobule)就会看到要你参见Double.toString(double)。

我那位朋友可能对Java不太熟悉,所以不太了解jdk,不过可不像我,没有一门精的,他可是C/C++这块的master
 

最后给大家提供一个网址是关于IEEE-754 Floating-Point Conversion的
http://babbage.cs.qc.edu/IEEE-754/Decimal.html

原创粉丝点击