1's complement and 2's complement Representation

一的补码(one's complement) 指的是正数=原码,负数=反码 
而二的补码(two's complement) 指的就是通常所指的补码

IP checksum definition

The IP checksum is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header.

One question many people may ask is "What is the 1's complement sum ?". This is because all computers utilize the 2's complement representation and the 1's complement is not used. The following gives a short introduction.

2's complement fixed point integers (8-bit)

BinaryDecimalHex
0000 0000000
0000 0001101
0000 0010202
0000 0011303
1111 1111-1FF
1111 1110-2FE
1111 1101-3FD

Let's add two intergers: 
-3 + 5 = 2 
FD + 05 = 01 02
Discarding the carry (01) gives the correct result.

1's complement fixed point integers (8-bit)

BinaryDecimalHex
0000 0000000
0000 0001101
0000 0010202
0000 0011303
1111 1111-0FF
1111 1110-1FE
1111 1101-2FD
1111 1100-3FC

Add the same numbers: 
-3 + 5 = 2
FC + 05 = 01 01
Adding the carry (01) to the LSB (01) gives the correct result:
01 + 01 = 02

So, the 1's complement sum is done by summing the numbers and adding the carry (or carries) to the result..

Simple Internet checksum example

Suppose we have an 8-bit, 2's complement, machine and send the packet

FE 05 00

where 00 is the checksum field.

Let's calculate and verify the Internet checksum.

 FE + 05  =  01 03

This is the result of the normal (2's complement) addition. The 1's complement sum requires the addition of the carry to the 8-bit word (even though we will not get the same result)

 03 + 01 = 04  

so the 1's complement sum of FE + 05 is 04.

The 1's complement of the 1's complement sum (Internet checksum) will be 

~04  = FB

and the packet will be sent as

FE 05 FB 

Now, at the receiving end we add all the received bytes, including the checksum (again using the 2's complement representation)

FE + 05 + FB  = 01 FE  

The 1's complement sum is  

 FE + 01 = FF = -0  

which checks that the transmission was OK (see below).

A more complex example (32-bit machine)

As shown in RFC 1071, the checksum calculation is done in the following way:

(1) Adjacent octets to be checksummed are paired to form 16-bit integers, and the 1's complement sum of these 16-bit integers is formed.

(2) To generate a checksum, the checksum field itself is cleared, the 16-bit 1's complement sum is computed over the octets concerned, and the 1's complement of this sum is placed in the checksum field.

(3) To check a checksum, the 1's complement sum is computed over the same set of octets, including the checksum field. If the result is all 1 bits (-0 in 1's complement arithmetic), the check succeeds.

Packet

01 00 F2 03 F4 F5 F6 F7 00 00

(00 00 is the checksum field)

Form the 16-bit words

0100 F203 F4F5 F6F7

Calculate 2's complement sum

0100 + F203 + F4F5 + F6F7 = 0002 DEEF (store the sum in a 32-bit word)

Add the carries (0002) to get the 16-bit 1's complement sum

DEEF + 002 = DEF1

Calculate 1's complement of the 1's complement sum

~DEF1 = 210E

We send the packet including the checksum 21 0E

01 00 F2 03 F4 F5 F6 F7 21 0E

At the receiving

0100 + F203 + F4F5 + F6F7 + 210E = 0002 FFFD
FFFD + 0002 = FFFF

which checks OK.

Comments
It may look awkword to use a 1's complement addition on 2's complement machines. This method however has its own benefits.

Probably the most important is that it is endian independent. Little Endian computers store hex numbers with the LSB last (Intel processors for example). Big Endian computers put the LSB first (IBM mainframes for example). When carry is added to the LSB to form the 1's complement sum (see the example) it doesn't matter if we add 03 + 01 or 01 + 03. The result is the same.

Other benefits include the easiness of checking the transmission and the checksum calculation plus a variety of ways to speed up the calculation by updating only IP fields that have changed.

 

 


The IP Header Checksum is computed on the header fields only. 
Before starting the calculation, the checksum fields (octets 11 and 12) 
are made equal to zero. 

In the example code, 
u16 buff[] is an array containing all octets in the header with octets 11 and 12 equal to zero. 
u16 len_ip_header is the length (number of octets) of the header.


/*
**************************************************************************
Function: ip_sum_calc
Description: Calculate the 16 bit IP sum.
***************************************************************************
*/
typedef unsigned short u16;
typedef unsigned long u32;

u16 ip_sum_calc(u16 len_ip_header, u16 buff[])
{
        u16 word16;
        u32 sum=0;
        u16 i;
    
        // make 16 bit words out of every two adjacent 8 bit words in the packet
        // and add them up
        for (i=0;i<len_ip_header;i=i+2){
                word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
                sum = sum + (u32) word16;
        }

        // take only 16 bits out of the 32 bit sum and add up the carries
        while (sum>>16)
                sum = (sum & 0xFFFF)+(sum >> 16);

        // one's complement the result
        sum = ~sum;

        return ((u16) sum);
}


 

### 小数 -1 的原码、反码和补码表示 对于小数 `-1`,其在计算机中的原码、反码和补码可以通过特定规则来计算。以下是详细的说明: #### 1. 原码表示 原码是最简单的编码方式,其中最高位为符号位(0 表示正数,1 表示负数),剩余部分为数值绝对值的二进制形式。假设字长为 n,则小数 `-1` 的原码可以写成如下形式: - 符号位:由于是负数,因此符号位为 `1`。 - 数值部分:将 `|−1| = 1` 转化为二进制并补齐到指定的小数精度。 例如,在字长为 8 位的情况下,小数 `-1` 的原码可表示为: ```plaintext 1.1000000 ``` 此处第一位为符号位,后续七位为数值部分[^1]。 #### 2. 反码表示 反码基于原码定义而来,当数值为正时,反码等于原码;而当数值为负时,需将原码除符号位外的所有位取反(即 0 变 11 变 0)。按照上述原则,小数 `-1` 的反码可通过以下步骤得出: - 首先写出 `-1` 的原码:`1.1000000`; - 接着对数值部分按位取反得到:`1.0111111`. 最终结果为: ```plaintext 1.0111111 ``` #### 3. 补码表示 补码用于简化加减运算处理过程,尤其适合硬件实现。针对负数而言,其补码是在反码基础上再加一形成。具体操作如下所示: - 已知 `-1` 的反码为 `1.0111111`; - 对该反码加上 `0.0000001`, 结果变为 `1.1000000`. 所以,小数 `-1` 的补码表达式应为: ```plaintext 1.1000000 ``` 值得注意的是,这种模式下零只有一种表现形式,有效避免了重复现象发生[^2]。 --- ### Python 实现代码 下面提供一段简单易懂的Python程序用来验证以上理论推导的结果: ```python def float_to_binary(number, precision=7): """Convert a floating-point number to its binary representation.""" integer_part = int(abs(number)) fractional_part = abs(number) - integer_part # Convert the integer part to binary and remove '0b' bin_integer = bin(integer_part)[2:] # Generate the fractional part as binary string up to given precision bin_fractional = "" while fractional_part > 0 and len(bin_fractional) < precision: fractional_part *= 2 bit = int(fractional_part) if bit == 1: fractional_part -= bit bin_fractional += '1' else: bin_fractional += '0' return f"{bin_integer}.{bin_fractional}" # Example usage for converting -1 with default precision of 7 bits after decimal point. number = -1 binary_representation = float_to_binary(number) print("Original Binary Representation:", binary_representation) original_code = "1." + "".join(['1' if c=='.' else ('0' if c=='1' else '1') for c in binary_representation.split('.')[1]]) print("One's Complement (反码):", original_code.replace('..', '.')) complement_two = list(original_code) if complement_two[-1]=='0': carry=True else: carry=False for i in range(len(complement_two)-1,-1,-1): if not carry or complement_two[i]!='.': break elif complement_two[i]=='0': complement_two[i]='1';carry=False;break; elif complement_two[i]=='1': complement_two[i]='0'; two_complement="".join(complement_two).replace("..",".") print("Two's Complement (补码):", two_complement) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值