“Java中的浮点型”的版本间的差异
Jihongchang(讨论 | 贡献) |
Jihongchang(讨论 | 贡献) |
||
(未显示同一用户的10个中间版本) | |||
第41行: | 第41行: | ||
0 |1 |0 |0 |0 |1 |1 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |1 |1 |0 |0 |1 |0 |0 |0 |1 |1 |1 |1 |1 |1 |0 | | 0 |1 |0 |0 |0 |1 |1 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |1 |1 |0 |0 |1 |0 |0 |0 |1 |1 |1 |1 |1 |1 |0 | | ||
</syntaxhighlight>Float.floatToIntBits(float value) 方法返回的 int 型数据,就是 float 输入参数的二进制形式转换成对应的十进制值。 | </syntaxhighlight>Float.floatToIntBits(float value) 方法返回的 int 型数据,就是 float 输入参数的二进制形式转换成对应的十进制值。 | ||
+ | |||
+ | |||
=== 十进制小数转二进制小数 === | === 十进制小数转二进制小数 === | ||
− | + | “12345.12345f”中, | |
− | + | ||
+ | ①整数部分“12345”应用除2取余得到的二进制形式是“11000000111001”;(参见:[[十进制和其他进制之间的转换]]) | ||
+ | |||
+ | ②小数部分“0.12345”应用乘2取整得到的二进制形式是“0.0001111111011010011……”。(参见:[[十进制小数转 IEEE 754 单精度浮点数]]) | ||
− | + | ③合在一起,12345.12345<sub>(10)</sub>=11000000111001.0001111110011010011……<sub>(2)</sub> | |
+ | |||
+ | ④用科学计数法表示,就是11000000111001.0001111110011010011……<sub>(2)</sub>=1.10000001110010001111110011010011……×2<sup>'''13'''</sup> | ||
+ | |||
+ | ⑤作为二进制小数,存储的时候不保存整数位的1(因为用科学计数法表示,整数部分一定是1),所以作为尾数存储的二进制部分就是小数点“.”后面的“'''<big>10000001110010001111111011010011</big>'''……” | ||
+ | |||
+ | ⑥此时能够发现和前面打印出的二进制部分中有效数(或者说尾数)的部分存储内容是相同的: | ||
{| class="wikitable" | {| class="wikitable" | ||
!符号位 | !符号位 | ||
− | ! colspan="8" |指数 | + | ! colspan="8" |指数/阶码 |
− | ! colspan="23" |有效数 | + | ! colspan="23" |有效数/尾数 |
|- | |- | ||
+ | !0 | ||
!1 | !1 | ||
!2 | !2 | ||
第84行: | 第96行: | ||
!30 | !30 | ||
!31 | !31 | ||
− | |||
|- | |- | ||
!+/- | !+/- | ||
− | ! | + | ! colspan="8" |十进制指数+127(正负幂的偏置修正值)转二进制 |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
!2<sup>-1</sup> | !2<sup>-1</sup> | ||
!2<sup>-2</sup> | !2<sup>-2</sup> | ||
第104行: | 第108行: | ||
!2<sup>-8</sup> | !2<sup>-8</sup> | ||
!2<sup>-9</sup> | !2<sup>-9</sup> | ||
− | !2-10 | + | !2<sup>-10</sup> |
− | ! | + | !2<sup>-11</sup> |
− | ! | + | !2<sup>-12</sup> |
− | ! | + | !2<sup>-13</sup> |
− | ! | + | !2<sup>-14</sup> |
− | ! | + | !2<sup>-15</sup> |
− | ! | + | !2<sup>-16</sup> |
− | ! | + | !2<sup>-17</sup> |
− | ! | + | !2<sup>-18</sup> |
− | ! | + | !2<sup>-19</sup> |
− | ! | + | !2<sup>-20</sup> |
− | ! | + | !2<sup>-21</sup> |
− | ! | + | !2<sup>-22</sup> |
− | ! | + | !2<sup>-22</sup> |
|- | |- | ||
|0 | |0 | ||
第128行: | 第132行: | ||
|0 | |0 | ||
|0 | |0 | ||
− | |1 | + | |'''<big>1</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |0 | + | |'''<big>0</big>''' |
− | |1 | + | |'''<big>1</big>''' |
− | |1 | + | |'''<big>1</big>''' |
+ | |'''<big>1</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>1</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |}⑦而指数(阶码)的部分就是:'''13'''+127=140<sub>(10)</sub>=10001100<sub>(2)</sub> | ||
+ | |||
+ | 附:阶码偏置值的出现是因为——从设计的角度看,我们希望除符号位外的阶码和尾数的二进制位数值整体上二进制数越大,它所代表的十进制数也就越大。 | ||
+ | |||
+ | |||
+ | === 那么浮点数有没有应用补码呢? === | ||
+ | 以“-1.5”为例:<syntaxhighlight lang="java"> | ||
+ | public class Test { | ||
+ | public static void main(String[] args) { | ||
+ | int intBits = Float.floatToIntBits(-1.5f); //Bit Representation of the Float | ||
+ | System.out.printf("intBits:%d\n", intBits); // | ||
+ | |||
+ | String binaryString = Integer.toBinaryString(intBits); | ||
+ | System.out.printf("binaryString:%s\n", binaryString); | ||
+ | |||
+ | String completeBinaryString = String.format("%32s", binaryString).replace(' ', '0'); | ||
+ | System.out.printf("binaryString补零后:%s\n", completeBinaryString); | ||
+ | |||
+ | System.out.println("格式化显示:"); | ||
+ | int i = 0; | ||
+ | System.out.printf("%-3d|", i++); | ||
+ | while (i < completeBinaryString.length()) { | ||
+ | System.out.printf("%-3d|", i++); | ||
+ | } | ||
+ | System.out.println(); | ||
+ | |||
+ | int j = 0; | ||
+ | System.out.printf("%-3c|", completeBinaryString.charAt(j++)); | ||
+ | while (j < completeBinaryString.length()) { | ||
+ | System.out.printf("%-3c|", completeBinaryString.charAt(j++)); | ||
+ | } | ||
+ | System.out.println("\n"); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight><syntaxhighlight lang="console"> | ||
+ | intBits:-1077936128 | ||
+ | binaryString:10111111110000000000000000000000 | ||
+ | binaryString补零后:10111111110000000000000000000000 | ||
+ | 格式化显示: | ||
+ | 0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 | | ||
+ | 1 |0 |1 |1 |1 |1 |1 |1 |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | | ||
+ | </syntaxhighlight>①整数部分“1”的二进制形式就是“1”; | ||
+ | |||
+ | ②小数部分“0.5”应用乘2取整得到的二进制形式是“0.1” | ||
+ | |||
+ | ③合在一起是 1.5<sub>(10)</sub>=1.1<sub>(2)</sub> | ||
+ | |||
+ | ④科学计数法:1.1<sub>(2)</sub>=1.1×2<sup>0</sup> | ||
+ | |||
+ | ⑤尾数部分只存小数部分就是“.1” | ||
+ | |||
+ | ⑥阶码部分:0+127(偏置修正)=127<sub>(10)</sub>=1111111<sub>(2)</sub> | ||
+ | |||
+ | ⑧以为是负数,所以首位符号位是1 | ||
+ | {| class="wikitable" | ||
+ | !符号位 | ||
+ | ! colspan="8" |指数/阶码 | ||
+ | ! colspan="23" |有效数/尾数 | ||
+ | |- | ||
+ | !0 | ||
+ | !1 | ||
+ | !2 | ||
+ | !3 | ||
+ | !4 | ||
+ | !5 | ||
+ | !6 | ||
+ | !7 | ||
+ | !8 | ||
+ | !9 | ||
+ | !10 | ||
+ | !11 | ||
+ | !12 | ||
+ | !13 | ||
+ | !14 | ||
+ | !15 | ||
+ | !16 | ||
+ | !17 | ||
+ | !18 | ||
+ | !19 | ||
+ | !20 | ||
+ | !21 | ||
+ | !22 | ||
+ | !23 | ||
+ | !24 | ||
+ | !25 | ||
+ | !26 | ||
+ | !27 | ||
+ | !28 | ||
+ | !29 | ||
+ | !30 | ||
+ | !31 | ||
+ | |- | ||
+ | !+/- | ||
+ | ! colspan="8" |十进制指数+127(正负幂的偏置修正值)转二进制 | ||
+ | !2<sup>-1</sup> | ||
+ | !2<sup>-2</sup> | ||
+ | !2<sup>-3</sup> | ||
+ | !2<sup>-4</sup> | ||
+ | !2<sup>-5</sup> | ||
+ | !2<sup>-6</sup> | ||
+ | !2<sup>-7</sup> | ||
+ | !2<sup>-8</sup> | ||
+ | !2<sup>-9</sup> | ||
+ | !2<sup>-10</sup> | ||
+ | !2<sup>-11</sup> | ||
+ | !2<sup>-12</sup> | ||
+ | !2<sup>-13</sup> | ||
+ | !2<sup>-14</sup> | ||
+ | !2<sup>-15</sup> | ||
+ | !2<sup>-16</sup> | ||
+ | !2<sup>-17</sup> | ||
+ | !2<sup>-18</sup> | ||
+ | !2<sup>-19</sup> | ||
+ | !2<sup>-20</sup> | ||
+ | !2<sup>-21</sup> | ||
+ | !2<sup>-22</sup> | ||
+ | !2<sup>-22</sup> | ||
+ | |- | ||
|1 | |1 | ||
|0 | |0 | ||
|1 | |1 | ||
− | |||
− | |||
− | |||
− | |||
|1 | |1 | ||
|1 | |1 | ||
第150行: | 第283行: | ||
|1 | |1 | ||
|1 | |1 | ||
− | |0 | + | |'''<big>1</big>''' |
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
+ | |'''<big>0</big>''' | ||
|} | |} | ||
+ | 对照一开始的代码输出结果,看来对于浮点数并没有应用补码的设计规则。 |
2022年11月14日 (一) 03:21的最新版本
怎样查看浮点型的二进制形式
以float为例:
public class Test2 {
public static void main(String[] args) {
int intBits = Float.floatToIntBits(12345.12346f); //Bit Representation of the Float
System.out.printf("intBits:%d\n", intBits); //1178657918
String binaryString = Integer.toBinaryString(intBits);
System.out.printf("binaryString:%s\n", binaryString);
String completeBinaryString = String.format("%32s", binaryString).replace(' ', '0');
System.out.printf("binaryString补零后:%s\n", completeBinaryString);
System.out.println("格式化显示:");
int i = 0;
System.out.printf("%-3d|", i++);
while (i < completeBinaryString.length()) {
System.out.printf("%-3d|", i++);
}
System.out.println();
int j = 0;
System.out.printf("%-3c|", completeBinaryString.charAt(j++));
while (j < completeBinaryString.length()) {
System.out.printf("%-3c|", completeBinaryString.charAt(j++));
}
System.out.println("\n");
}//end main
}
intBits:1178657918
binaryString:1000110010000001110010001111110
binaryString补零后:01000110010000001110010001111110
格式化显示:
0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |
0 |1 |0 |0 |0 |1 |1 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |1 |1 |0 |0 |1 |0 |0 |0 |1 |1 |1 |1 |1 |1 |0 |
Float.floatToIntBits(float value) 方法返回的 int 型数据,就是 float 输入参数的二进制形式转换成对应的十进制值。
十进制小数转二进制小数
“12345.12345f”中,
①整数部分“12345”应用除2取余得到的二进制形式是“11000000111001”;(参见:十进制和其他进制之间的转换)
②小数部分“0.12345”应用乘2取整得到的二进制形式是“0.0001111111011010011……”。(参见:十进制小数转 IEEE 754 单精度浮点数)
③合在一起,12345.12345(10)=11000000111001.0001111110011010011……(2)
④用科学计数法表示,就是11000000111001.0001111110011010011……(2)=1.10000001110010001111110011010011……×213
⑤作为二进制小数,存储的时候不保存整数位的1(因为用科学计数法表示,整数部分一定是1),所以作为尾数存储的二进制部分就是小数点“.”后面的“10000001110010001111111011010011……”
⑥此时能够发现和前面打印出的二进制部分中有效数(或者说尾数)的部分存储内容是相同的:
符号位 | 指数/阶码 | 有效数/尾数 | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
+/- | 十进制指数+127(正负幂的偏置修正值)转二进制 | 2-1 | 2-2 | 2-3 | 2-4 | 2-5 | 2-6 | 2-7 | 2-8 | 2-9 | 2-10 | 2-11 | 2-12 | 2-13 | 2-14 | 2-15 | 2-16 | 2-17 | 2-18 | 2-19 | 2-20 | 2-21 | 2-22 | 2-22 | |||||||
0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
⑦而指数(阶码)的部分就是:13+127=140(10)=10001100(2)
附:阶码偏置值的出现是因为——从设计的角度看,我们希望除符号位外的阶码和尾数的二进制位数值整体上二进制数越大,它所代表的十进制数也就越大。
那么浮点数有没有应用补码呢?
以“-1.5”为例:
public class Test {
public static void main(String[] args) {
int intBits = Float.floatToIntBits(-1.5f); //Bit Representation of the Float
System.out.printf("intBits:%d\n", intBits); //
String binaryString = Integer.toBinaryString(intBits);
System.out.printf("binaryString:%s\n", binaryString);
String completeBinaryString = String.format("%32s", binaryString).replace(' ', '0');
System.out.printf("binaryString补零后:%s\n", completeBinaryString);
System.out.println("格式化显示:");
int i = 0;
System.out.printf("%-3d|", i++);
while (i < completeBinaryString.length()) {
System.out.printf("%-3d|", i++);
}
System.out.println();
int j = 0;
System.out.printf("%-3c|", completeBinaryString.charAt(j++));
while (j < completeBinaryString.length()) {
System.out.printf("%-3c|", completeBinaryString.charAt(j++));
}
System.out.println("\n");
}
}
intBits:-1077936128
binaryString:10111111110000000000000000000000
binaryString补零后:10111111110000000000000000000000
格式化显示:
0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |
1 |0 |1 |1 |1 |1 |1 |1 |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |
①整数部分“1”的二进制形式就是“1”;
②小数部分“0.5”应用乘2取整得到的二进制形式是“0.1”
③合在一起是 1.5(10)=1.1(2)
④科学计数法:1.1(2)=1.1×20
⑤尾数部分只存小数部分就是“.1”
⑥阶码部分:0+127(偏置修正)=127(10)=1111111(2)
⑧以为是负数,所以首位符号位是1
符号位 | 指数/阶码 | 有效数/尾数 | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
+/- | 十进制指数+127(正负幂的偏置修正值)转二进制 | 2-1 | 2-2 | 2-3 | 2-4 | 2-5 | 2-6 | 2-7 | 2-8 | 2-9 | 2-10 | 2-11 | 2-12 | 2-13 | 2-14 | 2-15 | 2-16 | 2-17 | 2-18 | 2-19 | 2-20 | 2-21 | 2-22 | 2-22 | |||||||
1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
对照一开始的代码输出结果,看来对于浮点数并没有应用补码的设计规则。