【发布时间】:2011-08-02 06:04:56
【问题描述】:
只需添加位即可生成校验和。采取 1s 补码的额外步骤有何用处?
我理解这个理论。我知道如何计算 1 的补码,并且我知道添加补码如何使结果全为 1。
我想看一个如何检测错误的简单示例。
【问题讨论】:
标签: checksum
只需添加位即可生成校验和。采取 1s 补码的额外步骤有何用处?
我理解这个理论。我知道如何计算 1 的补码,并且我知道添加补码如何使结果全为 1。
我想看一个如何检测错误的简单示例。
【问题讨论】:
标签: checksum
我相信您正在寻找的示例可以在 here 找到。
我们做 1 的补码的原因是,当 1 的补码加到所有值的总和上,并将结果修剪到机器的位长(上例中为 16 位)时,都是1的。 CPU 具有取数字补码 1 的特性,取全 1 的 1 补码就是全 0。
原因:CPU 讨厌使用比特,除了它通常使用的多块。因此,添加两个 64 位数字可能需要 1 个周期,但单独检查该数字的所有位将花费更多(在一个简单的循环中,可能高达 8x64 个周期)。 CPU 也有能力简单地取 1 的补码,并检测最后一次计算的结果是否为零,而无需检查单个位和基于此的分支。所以基本上,它是一种优化,可以让我们非常快速地检查校验和。由于大多数数据包都很好,这让我们可以即时检查校验和并更快地将数据发送到目的地。
【讨论】:
例如,您需要发送 UDP 数据包中的三个字。
0110011001100000
0101010101010101
1000111100001100
发送方的 UDP 对所有 16 位的总和进行 1 的补码 字。这些 16 位字中前两个字的和是
0110011001100000
+
0101010101010101
--> 1011101110110101
将第三个单词添加到上面的总和中,请注意,最后一个添加有溢出,它被环绕
--> 0100101011000010
1s补码是通过将所有0转换为1并将所有1转换为0来获得的。
因此和 0100101011000010 的补码是 1011010100111101,它成为校验和。在接收端,所有四个 16 位字都被添加,包括校验和。如果数据包中没有引入错误,那么显然接收方的总和将是1111111111111111。如果其中一位是 0,那么我们就知道数据包中引入了错误。
【讨论】:
校验和的反码(位反转)至少在两个方面很有用。
例如,如果最终校验和字节为 56,则补码(位反转)将为 199。将它们加在一起,结果为 255。推理:通过对最终校验和进行补码,最终结果将始终为 255当在总和计算中包含校验和数字时。用 255 再次执行补码将产生 0,这对于当时的 CPU 来说是一种更有效的方式来确认校验和是否有效,而无需比较两个数字。
计算 n 个零的消息会产生零校验和。这意味着由零组成的合法消息与应该被检测为错误的内存丢失或擦除情况无法区分。在这种情况下,通过补充最终校验和 0,结果变为 255,从而防止结果为零仍然有效。
【讨论】:
通过“添加位”,我假设您的意思是计算奇偶校验位。根据this Wikipedia entry on checksums,对于奇偶校验和“未检测到两位错误的概率为 1/n”,而使用模和(例如 1s 补码)“未检测到两位错误的概率为略小于 1/n。”
This "Ask Dr. Math" column 讨论如何计算 1 的补码(最常见于 TCP/IP)。
【讨论】:
正如 partickmdnet 所提到的,校验和对于网络非常重要。基本上,对于在 IP 协议中传输的每个数据报,都有一个提前计算并传输的校验和。如果在数据报的数据部分中甚至有一位被损坏并错误发送,那么在接收路由器计算的校验和将与数据报提供的校验和不同。这告诉路由器数据报已损坏(数据或校验和部分本身),路由器将丢弃数据报。
【讨论】: