Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么可以';t 0.2(以10为基数)用二进制表示为0.10(以2为基数)_Java_Binary_Floating Point - Fatal编程技术网

Java 为什么可以';t 0.2(以10为基数)用二进制表示为0.10(以2为基数)

Java 为什么可以';t 0.2(以10为基数)用二进制表示为0.10(以2为基数),java,binary,floating-point,Java,Binary,Floating Point,我一直在读java中的浮点类型,比如double。 我也读过关于将分数转换成二进制以及如何转换的书。 我可以做数学运算,发现用二进制表示0.2是以下近似值: 0.00110011001100... 然而,二进制中的2是10。 那么为什么我不能说0.2(基数10)等于0.10(基数2) 我读过一篇类似的文章,但我仍然对此感到困惑 另一个例子是5.8 101.110011001100... 为什么我们不能:101.1000,因为二进制中的8是1000 我知道0.10和0.1000是相同的,但在这

我一直在读java中的浮点类型,比如double。 我也读过关于将分数转换成二进制以及如何转换的书。 我可以做数学运算,发现用二进制表示0.2是以下近似值:

0.00110011001100...
然而,二进制中的2是10。 那么为什么我不能说0.2(基数10)等于0.10(基数2)

我读过一篇类似的文章,但我仍然对此感到困惑

另一个例子是5.8

101.110011001100...
为什么我们不能:101.1000,因为二进制中的8是1000


我知道0.10和0.1000是相同的,但在这种情况下,它们是分开的。

因为这与不同基数中的数字表示方式不一致:

如果您有一个二进制数,比如说
1100.101
,它用base 2表示,因此要将其转换为base 10,您需要执行以下操作:

... 2^3   2²   2^1  2^0  .  2^-1   2^-2   2^-3 ...
    1     1    0    0    .  1      0      1
这意味着您有
2^3+2²+2^-1+2^-3=基数10中的数字

注意,指数总是从左向右减少一。所以基本上,当你向右移动一个数字时,你就是在除以基数,在这个例子中是除以
2

这就是数字在任何给定基B中的表示方式。对于B您有

... B^3   B²   B^1  B^0  .  B^-1   B^-2   B^-3 ...
就你的例子而言,这意味着:

0.2 = 2 * 10^-1   //base 10 (= 0.2 in base 10)
0.2 = 2 * 2^-1    //base 2
0.1 = 1 * 10^-1   //base 10
0.1 = 1 * 2^-1    //base 2  (= 0.5 in base 10)
这就是为什么基数10中的
0.2
不是并且在基数2中不能是
0.1


你甚至还说
0.10
0.1000
在你的表述中是不同的数字。(这不仅毫无意义,而且对任何计算机来说都是一场噩梦)

因为这与不同基数中的数字表示方式不一致:

如果您有一个二进制数,比如说
1100.101
,它用base 2表示,因此要将其转换为base 10,您需要执行以下操作:

... 2^3   2²   2^1  2^0  .  2^-1   2^-2   2^-3 ...
    1     1    0    0    .  1      0      1
这意味着您有
2^3+2²+2^-1+2^-3=基数10中的数字

注意,指数总是从左向右减少一。所以基本上,当你向右移动一个数字时,你就是在除以基数,在这个例子中是除以
2

这就是数字在任何给定基B中的表示方式。对于B您有

... B^3   B²   B^1  B^0  .  B^-1   B^-2   B^-3 ...
就你的例子而言,这意味着:

0.2 = 2 * 10^-1   //base 10 (= 0.2 in base 10)
0.2 = 2 * 2^-1    //base 2
0.1 = 1 * 10^-1   //base 10
0.1 = 1 * 2^-1    //base 2  (= 0.5 in base 10)
这就是为什么基数10中的
0.2
不是并且在基数2中不能是
0.1


你甚至还说
0.10
0.1000
在你的表述中是不同的数字。(这不仅没有任何意义,而且对任何计算机来说都是一场噩梦)

出于同样的原因,1/3是以10为基数的非终止小数,0.2或1/5是以2为基数的非终止小数。请注意,二进制数的小数部分的工作方式与基数10相同,其中基数10中的0.1表示10^-1,基数2中的0.1表示2^-1或0.5。同样,基数2中的0.01为1/4,0.001为1/8。因为二的幂的有限和不能等于分母中不是二的幂的分数,所以这些数字是非终止的。在实际应用中,这可能会导致浮点运算出现问题,因为舍入会产生意外的结果。正是因为这个原因,使用浮点数的相等性测试最好在误差范围内完成,比如0.01%


另请参见:

出于同样的原因,1/3是以10为基数的非终止小数,0.2或1/5是以2为基数的非终止小数。请注意,二进制数的小数部分的工作方式与基数10相同,其中基数10中的0.1表示10^-1,基数2中的0.1表示2^-1或0.5。同样,基数2中的0.01为1/4,0.001为1/8。因为二的幂的有限和不能等于分母中不是二的幂的分数,所以这些数字是非终止的。在实际应用中,这可能会导致浮点运算出现问题,因为舍入会产生意外的结果。正是因为这个原因,使用浮点数的相等性测试最好在误差范围内完成,比如0.01%


另请参见:

因为基数2中的0.1是基数10中的0.5(
1/(2**1)
)?为什么二进制数和十进制数完全不一致?在您的系统中,删除尾随的零会改变数字,但您可能知道5.8(通常)与您刚刚重新发明的5.8000相同。@PatriciaShanahan
许多非整数值,如十进制0.2,具有二进制的无限位值表示形式(.001100110011…)但在二进制编码的十进制(0.0010)中有一个有限位值。因此,基于十进制分数的二进制编码十进制表示法的系统避免了表示和计算此类值的错误。
我想这就是我的意思。通过回答和更多的研究,我意识到了为什么这在java中是不可能的,但我从来没有听说过bcd。@eric在java中,当你需要有限长小数的精确表示时,你应该使用BigDecimal。我同意@Patricia。在Java中,如果您需要精确的十进制表示和几乎无限(或者定义良好,如果您愿意)的精度,请使用BigDecimal?为什么二进制数和十进制数完全不一致?在您的系统中,删除尾随的零会改变数字,但您可能知道5.8(通常)与您刚刚重新发明的5.8000相同。@PatriciaShanahan
许多非整数值,如十进制0.2,具有二进制的无限位值表示形式(.001100110011…)但在二进制编码的十进制(0.0010)中有一个有限位值。因此,基于十进制分数的二进制编码十进制表示的系统避免了表示和计算su的错误