通过将 2 除以减一来移位

问题描述 投票:0回答:1

在Java中,我试图通过除以2而不是右移(>>1)来将整数的位右移一位,并且遇到了这个问题,即-1(负数)除以2时无法正确移动。有人能解释一下为什么负数除以2不起作用吗? Code Terminal

我尝试过使用正数并且它们有效,但我不明白为什么除以 2 不适用于负数

java bit-manipulation bit-shift divide
1个回答
0
投票

计算机是二进制的。例如,1 和 0 是他们唯一可以写的字母。这实际上是“唯一的”——因此,负数“不可能存在”。或者至少,减号是不存在的。这并不是说计算机可以秘密地表示 3 个东西(一、零和减号)。这只是 1 和 0。仅此而已。 这意味着您需要一个表示负数的计划。没有明显的答案(假设 - 在最低级别不存在)。

在大多数计算机系统中,java 在规范中“硬编码”此行为,所选择的解决方案称为 2 的补码。

2 的补码通过切换每一位(所有 1 变为 0,所有 0 变为 1)产生任何给定数字的负版本,然后将 1 添加到最终结果。

这听起来很奇怪,但是它有许多非常有用的属性:

与使用单独的“符号”位(0 = 正,1 = 负)或只是翻转所有位而不在末尾添加 1 相比,2 的补码只有 1 表示 0。也就是说,- 0 与+0 相同。我们来试试:0 位表示为

0000 0000
    。翻转所有位:
  • 1111 1111

    ,然后添加一个:

    1 0000 0000
    ,但前 1 位会消失,因为计算机忽略任何溢出,所以我们回到开始的地方:
    0000 0000
    。这是好事。 0 也是唯一一个具有等于自身负数的性质的数字。
    
    
    -1 变为全 1 位。 (1 是 

    0000 0001
  • ,翻转所有位:
  • 1111 1110

    ,然后添加 1:

    1111 1111
    )。这有一定的优势。
    
    
    第一位表示符号。如果第一位是 1,则该数字必然为负数。那就太好了。

  • 可以表示的负数比正数多 1 个。这很奇怪,也不是一件好事,但这是将 0(从技术上讲既不是正数也不是负数)与正数分组的自然结果。零“吃掉”一格的积极因素。

  • 2 的补码的

    关键
  • 优点是必须应用来执行加法和减法的公式
  • 不关心

    输入是带符号还是无符号的2的补码。因为公式是一样的。假设我有 2 个无符号字节,我想将 200 和 50 加在一起。这是以位 1100 1000 + 0011 0010 为单位的,即 1111 1010。将其转换回十进制,结果是 250。这是预期的答案。然而,实际上,这些是 2 的补码有符号数,所以,

    0011 0010
    仍然是 50,但
    1100 1000
    不是:那就是(翻转所有位并加 1):负
    0011 1000
    是 -56。 -56 + 50 是 -6,2 的补码是
    0000 0110
    (即 6,现在翻转所有位并加 1):
    1111 1010
    这是...哇,这与我们处理2 个数字作为无符号正数。
    
    
    太棒了。这就是 2 的补码的原因。

  • 至关重要的是,整个“哇,要做加法或减法,只需将所有位加在一起,就可以了,作为计算机,你不需要知道这些数字是否代表 2 的补码有符号值或无符号值”
不适用于乘法和除法。

用整数来思考,这是完全有道理的:负一除以 2 当然是负二分之一。 -1 的二进制表示是

1111 1111。当你右移一位时(就像除以 2 得到正数),你最终会得到 0111 1111

。这是 127。

“除以 2 与右移 1 相同”根本不适用于负数(当然不适用于 2 的补码中的负数)。

© www.soinside.com 2019 - 2024. All rights reserved.