一、整型数据类型
C 语言支持多种整型数据类型——表示有限范围的整数。
- 每种类型都能用关键字来指定大小,这些关键字包括
char
、short
、long
,同时还可以指示被表示的数字是非负数(声明为unsigned
),或者可能是负数(默认)。 - 以下为 64 位程序上 C 语言整型数据类型的典型取值范围:
C 数据类型 | 最小值 | 最大值 |
---|---|---|
[signed] char | -128 | 127 |
unsigned char | 0 | 255 |
short | -32 768 | 32 767 |
unsigned short | 0 | 65 535 |
int | -2 147 483 648 | 2 147 483 647 |
unsigned | 0 | 4 294 967 295 |
long | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
unsigned long | 0 | 18 446 744 073 709 551 615 |
int32_t | -2 147 483 648 | 2 147 483 647 |
uint32_t | 0 | 4 294 967 295 |
int64_t | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
uint64_t | 0 | 18 446 744 073 709 551 615 |
二、无符号数的编码
-
假设有一个整数数据类型有 w w w 位。我们可以将位向量写成 x ⃗ \vec{x} x ,表示整个向量,或者写成 [ x w − 1 x_{w-1} xw−1 , x w − 2 x_{w-2} xw−2 , … , x 0 x_{0} x0 ],表示向量中的每一位。把 x ⃗ \vec{x} x 看做一个二进制表示的数,就获得了 x ⃗ \vec{x} x 的无符号表示。
-
在这个编码中,每个位 x i x_{i} xi 都取值为 0 或 1,后一种取值意味着数值 2 i 2^{i} 2i 应为数字值的一部分。我们用一个函数 B 2 U w B2U_{w} B2Uw ( Binary to Unsigned 的缩写,长度为 w w w )来表示:
-
原理:无符号数编码的定义。
-
对向量 x ⃗ \vec{x} x=[ x w − 1 x_{w-1} xw−1 , x w − 2 x_{w-2} xw−2 , … , x 0 x_{0} x0 ] :
B 2 U w ( x ⃗ ) = ˙ ∑ i = 0 w − 1 x i 2 i B2U_{w}(\vec{x}) \dot{=} \sum{i=0}^{w-1}x_{i}2^{i} B2Uw(x)=˙∑i=0w−1xi2i
-
在这个等式中,符号 “ = ˙ \dot{=} =˙” 表示左边被定义为等于右边。函数 B 2 U w B2U_{w} B2Uw ,将一个长度为 w w w 的 0、1 串映射到非负整数。
-
举一个示例,下面几种情况下 B 2 U B2U B2U 给出的从位向量到整数的映射:
- B 2 U 4 ( [ 0001 ] ) = 0 ⋅ 2 3 + 0 ⋅ 2 2 + 0 ⋅ 2 1 + 1 ⋅ 2 0 = 0 + 0 + 0 + 1 = 1 B2U_{4}([0001]) = 0 \cdot 2^{3} + 0 \cdot 2^{2} + 0 \cdot 2^{1} + 1 \cdot 2^{0} = 0 + 0 + 0 + 1 = 1 B2U4([0001])=0⋅23+0⋅22+0⋅21+1⋅20=0+0+0+1=1
- B 2 U 4 ( [ 0101 ] ) = 0 ⋅ 2 3 + 1 ⋅ 2 2 + 0 ⋅ 2 1 + 1 ⋅ 2 0 = 0 + 4 + 0 + 1 = 5 B2U_{4}([0101]) = 0 \cdot 2^{3} + 1 \cdot 2^{2} + 0 \cdot 2^{1} + 1 \cdot 2^{0} = 0 + 4 + 0 + 1 = 5 B2U4([0101])=0⋅23+1⋅22+0⋅21+1⋅20=0+4+0+1=5
- B 2 U 4 ( [ 1011 ] ) = 1 ⋅ 2 3 + 0 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 = 8 + 0 + 2 + 1 = 11 B2U_{4}([1011]) = 1 \cdot 2^{3} + 0 \cdot 2^{2} + 1 \cdot 2^{1} + 1 \cdot 2^{0} = 8 + 0 + 2 + 1 = 11 B2U4([1011])=1⋅23+0⋅22+1⋅21+1⋅20=8+0+2+1=11
- B 2 U 4 ( [ 1111 ] ) = 1 ⋅ 2 3 + 1 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 = 8 + 4 + 2 + 1 = 15 B2U_{4}([1111]) = 1 \cdot 2^{3} + 1 \cdot 2^{2} + 1 \cdot 2^{1} + 1 \cdot 2^{0} = 8 + 4 + 2 + 1 = 15 B2U4([1111])=1⋅23+1⋅22+1⋅21+1⋅20=8+4+2+1=15
-
w w w=4 的无符号数示例,当二进制表示中位 i i i 为 1,数值就会相应加上 2 i 2^{i} 2i:
-
让我们来考虑一下 w w w 位所能表示的值的范围:
- 最小值是用位向量 [ 00 … 0 ] [00…0] [00…0] 表示,也就是整数值0。
- 而最大值是用位向量 [ 11 … 1 ] [11…1] [11…1] 表示,也就是整数值 U M a x w = ˙ ∑ i = 0 w − 1 2 i = 2 w − 1 UMax_{w} \dot{=} \sum{i=0}^{w-1}{2^i} = 2^{w}-1 UMaxw=˙∑i=0w−12i=2w−1 ,以 4 位数情况为例, U M a x 4 = B 2 U 4 ( [ 1111 ] ) = 2 4 − 1 = 15 UMax_{4} = B2U_{4}([1111]) = 2^{4}-1 = 15 UMax4=B2U4([1111])=24−1=15 。因此,函数 B 2 U w B2U_{w} B2Uw 能够被定义为一个映射 B 2 U : { 0 , 1 } w → { 0 , . . . , 2 w − 1 } B2U:\{0,1\}^{w} \rightarrow \{0, ...,2^{w}-1\} B2U:{0,1}w→{0,...,2w−1}。
-
无符号数的二进制表示有一个很重要的属性,也就是每个介于 0 ∼ 2 w − 1 0 \sim 2^{w}-1 0∼2w−1 之间的数都有唯一一个 w w w 位的值编码。例如,十进制值 11 作为无符号数,只有一个 4 位的表示,即 [ 1011 ] [1011] [1011]。
-
我们用数学原理来重点讲述它,先表述原理再解释。
-
原理:无符号数编码的唯一性。
-
函数 B 2 U w B2U_{w} B2Uw 是一个双射。
-
数学术语 双射 是指一个函数 f f f 有两面:它将数值 x x x 映射为数值 y y y ,即 y = f ( x ) y=f(x) y=f(x),但它也可以反向操作,因为对每一个 y y y 而言,都有唯一一个数值 x x x 使得 f ( x ) = y f(x)=y f(x)=y 。这可以用 反函数 f − 1 f^{-1} f−1 来表示,在本例中,即 x = f − 1 ( y ) x = f^{-1}(y) x=f−1(y)。函数 B 2 U w B2U_{w} B2Uw ,将每一个长度为 w w w 的位向量都映射为 0 ∼ 2 w − 1 0 \sim 2^{w}-1 0∼2w−1 之间的一个唯一值;反过来,我们称其为 U 2 B w U2B_{w} U2Bw ,(即“无符号数到二进制”),在 0 ∼ 2 w − 1 0 \sim 2^{w}-1 0∼2w−1 之间的每一个整数都可以映射为一个唯一的长度为 w w w 的位模式。
三、补码编码
对于许多应用,我们还希望表示负数值。
- 最常见的有符号数的计算机表示方式就是补码( two ’ s - complement )形式。在这个定义中,将字的最高有效位解释为负权( negative weight )。我们用函数 B 2 T w B2T_{w} B2Tw 。( Binary to Two ’ s - complement 的缩写,长度为 w w w )来表示:
- 原理:补码编码的定义。
- 对向量 x ⃗ \vec{x} x=[ x w − 1 x_{w-1} xw−1 , x w − 2 x_{w-2} xw−2 , … , x 0 x_{0} x0 ] :
B 2 T w ( x ⃗ ) = ˙ − x w − 1 2 w − 1 + ∑ i = 0 w − 2 x i 2 i B2T_{w}(\vec{x}) \dot{=} -x_{w-1}{2^{w-1}} + \sum_{i=0}^{w-2}x_{i}2^{i} B2Tw(x)=˙−xw−12w−1+i=0∑w−2xi2i
-
最高有效位 x w − 1 x_{w-1} xw−1 也称为符号位,它的“权重“为 − 2 w − 1 -2_{w-1} −2w−1,是无符号表示中权重的负数。符号位被设置为 1 时,表示值为负,而当设置为 0 时,值为非负。
-
这里来看一个示例,下面几种情况下 B 2 T B2T B2T 给出的从位向量到整数的映射:
- B 2 T 4 ( [ 0001 ] ) = − 0 ⋅ 2 3 + 0 ⋅ 2 2 + 0 ⋅ 2 1 + 1 ⋅ 2 0 = 0 + 0 + 0 + 1 = 1 B2T_{4}([0001]) = - 0 \cdot 2^{3} + 0 \cdot 2^{2} + 0 \cdot 2^{1} + 1 \cdot 2^{0} = 0 + 0 + 0 + 1 = 1 B2T4([0001])=−0⋅23+0⋅22+0⋅21+1⋅20=0+0+0+1=1
- B 2 T 4 ( [ 0101 ] ) = − 0 ⋅ 2 3 + 1 ⋅ 2 2 + 0 ⋅ 2 1 + 1 ⋅ 2 0 = 0 + 4 + 0 + 1 = 5 B2T_{4}([0101]) = -0 \cdot 2^{3} + 1 \cdot 2^{2} + 0 \cdot 2^{1} + 1 \cdot 2^{0} = 0 + 4 + 0 + 1 = 5 B2T4([0101])=−0⋅23+1⋅22+0⋅21+1⋅20=0+4+0+1=5
- B 2 T 4 ( [ 1011 ] ) = − 1 ⋅ 2 3 + 0 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 = − 8 + 0 + 2 + 1 = − 5 B2T_{4}([1011]) = -1 \cdot 2^{3} + 0 \cdot 2^{2} + 1 \cdot 2^{1} + 1 \cdot 2^{0} = -8 + 0 + 2 + 1 = -5 B2T4([1011])=−1⋅23+0⋅22+1⋅21+1⋅20=−8+0+2+1=−5
- B 2 T 4 ( [ 1111 ] ) = − 1 ⋅ 2 3 + 1 ⋅ 2 2 + 1 ⋅ 2 1 + 1 ⋅ 2 0 = − 8 + 4 + 2 + 1 = − 1 B2T_{4}([1111]) = -1 \cdot 2^{3} + 1 \cdot 2^{2} + 1 \cdot 2^{1} + 1 \cdot 2^{0} = -8 + 4 + 2 + 1 = -1 B2T4([1111])=−1⋅23+1⋅22+1⋅21+1⋅20=−8+4+2+1=−1
-
w w w=4 的补码示例,把位 3 作为符号位,因此当它为 1 时,对数值的影响是 − 2 3 = − 8 -2^{3}=-8 −23=−8 。(这个权重在图中用带向左箭头的条表示):
-
让我们来考虑一下 w w w 位补码所能表示的值的范围。它能表示的最小值是位向量 [ 10...0 ] [10...0] [10...0](也就是设置这个位为负权,但是清除其他所有的位),其整数值为 T M i n w = ˙ − 2 w − 1 TMin_{w} \dot{=} -2^{w-1} TMinw=˙−2w−1 。而最大值是位向量 [ 01...1 ] [01...1] [01...1](清除具有负权的位,而设置其他所有的位),其整数值为 T M a x w = ˙ ∑ i = 0 w − 2 2 i = 2 w − 1 − 1 TMax_{w} \dot{=} \sum_{i=0}^{w-2}2^{i}=2^{w-1}-1 TMaxw=˙∑i=0w−22i=2w−1−1 。以长度为 4 为例,我们有 T M i n 4 = B 2 T 4 ( [ 1000 ] ) = − 2 3 = − 8 TMin_{4}=B2T_{4}([1000])=-2^{3}=-8 TMin4=B2T4([1000])=−23=−8 ,而 T M a x 4 = B 2 T 4 ( [ 0111 ] ) = 2 2 + 2 1 + 2 0 = 4 + 2 + 1 = 7 TMax_{4}=B2T_{4}([0111])=2^{2}+ 2^{1}+2^{0}=4+2+1=7 TMax4=B2T4([0111])=22+21+20=4+2+1=7 。
-
我们可以看出 B 2 T w B2T_{w} B2Tw 是一个从长度为 w {w} w 的位模式到 T M i n w TMin_{w} TMinw ,和 T M a x w TMax_{w} TMaxw 之间数字的映射,写作 B 2 T w B2T_{w} B2Tw : { 0 , 1 } w → { T m i n w , . . . , T M a x w } \{0,1\}^{w} \to \{Tmin_{w},...,TMax_{w}\} {0,1}w→{Tminw,...,TMaxw}。同无符号表示一样,在可表示的取值范围内的每个数字都有一个唯一的 w {w} w 位的补码编码。这就导出了与无符号数相似的补码数原理:
- 原理:补码编码的唯一性。
- 函数 B 2 T w B2T_{w} B2Tw 是一个 双射。
-
我们定义函数 T 2 B w T2B_{w} T2Bw (即“补码到二进制”)作为 B 2 T w B2T_{w} B2Tw 的反函数。也就是说,对于每个数 x {x} x ,满足 T M i n w ≤ x ≤ T M a x w TMin_{w} \leq x \leq TMax_{w} TMinw≤x≤TMaxw ,则 T 2 B w ( x ) T2B_{w}(x) T2Bw(x) 是 x {x} x 的(唯一的) w {w} w 位模式。
-
下表展示了不同字长,几个重要数字的位模式和数值(前三个给出的是可表示的整数的范围):
字长 w w w | ||||
---|---|---|---|---|
数 | 8 | 16 | 32 | 64 |
U M a x w UMax_{w} UMaxw | 0xFF 255 | 0×FFFF 65 535 | 0xFFFFFFFF 4 294 967 295 | 0xFFFFFFFFFFFFFFFF 18 446 744 073 709 551 615 |
T M i n w TMin_{w} TMinw | 0x80 -128 | 0x8000 -32 768 | 0x80000000 -2 147 483 648 | 0x8000000000000000 -9223 372 036 854775 808 |
T M a x w TMax_{w} TMaxw | 0x7F 127 | 0x7FFF 32 767 | 0x7FFFFFFF 2 147 483 647 | 0x7FFFFFFFFFFFFFFF 9 223 372 036 854 775 807 |
-1 0 | 0xFF 0×00 | 0xFFFF 0×0000 | 0xFFFFFFFF 0x00000000 | 0xFFFFFFFFFFFFFFFF 0x0000000000000000 |
-
关于这些数字,有几点值得注意:
- 第一,补码的范围是不对称的: ∣ T M i n ∣ = ∣ T M a x ∣ + 1 |{TMin}|=|{TMax}|+1 ∣TMin∣=∣TMax∣+1,也就是说, T M i n TMin TMin 没有与之对应的正数。正如我们将会看到的,这导致了补码运算的某些特殊的属性,并且容易造成程序中细微的错误。之所以会有这样的不对称性,是因为一半的位模式(符号位设置为 1 的数)表示负数,而另一半(符号位设置为 0 的数)表示非负数。因为 0 是非负数,也就意味着能表示的整数比负数少一个。
- 第二,最大的无符号数值刚好比补码的最大值的两倍大一点: U M a x w = 2 T M a x w 十 1 UMax_{w}=2TMax_{w}十1 UMaxw=2TMaxw十1 。 补码表示中所有表示负数的位模式在无符号表示中都变成了正数。上表也给出了常数 -1 和 0 的表示。注意 -1 和 U M a x UMax UMax 有同样的位表示 —— 一个全 1 的串。数值 0 在两种表示方式中都是全 0 的串。
- 如果希望代码具有最大可移植性,能够在所有可能的机器上运行,那么除了所示的那些范围之外,我们不应该假设任何可表示的数值范围,也不应该假设有符号数会使用何种特殊的表示方式。
- 关于整数数据类型的取值范围和表示, Java 标准是非常明确的。它要求采用补码表示。举个例子,在 Java 中,单字节数据类型称为
byte
,而不是char
。这些非常具体的要求都是为了保证无论在什么机器上运行, Java 程序都能表现地完全一样。
四、有符号数和无符号数之间的转换
C 语言允许在各种不同的数字数据类型之间做强制类型转换。
- 示例代码:
short intv = -12345;
unsigned short uv = (unsigned short)v;
printf("v = %d, uv = %u\n", v, uv);
- 在一台采用补码的机器上,上述代码会产生如下输出:
ν=-12345, uν = 53191
-
对于大多数 C 语言的实现,处理同样字长的有符号数和无符号数之间相互转换的一般规则是:数值可能会改变,但是位模式不变。
-
我们考虑无符号与补码表示之间互相转换的结果:
-
对于在范围 0 ≤ x ≤ T M a x w 0 \leq x \leq TMax_{w} 0≤x≤TMaxw 之内的值 x x x 而言,我们得到 T 2 U w ( x ) = x T2U_{w}(x)=x T2Uw(x)=x 和 U 2 T w ( x ) = x U2T_{w}(x)=x U2Tw(x)=x。也就是说,在这个范围内的数字有相同的无符号和补码表示。
-
对于这个范围以外的数值,转换需要加上或者减去 2 w 2^{w} 2w。例如,我们有 T 2 U w ( − 1 ) = − 1 + 2 w = U M a x w T2U_{w}(-1)=-1+2^{w}=UMax_{w} T2Uw(−1)=−1+2w=UMaxw —— 最靠近 0 的负数映射为最大的无符号数。
-
在另一个极端,我们可以看到 T 2 U w ( T M i n w ) = − 2 w − 1 + 2 w = 2 w − 1 = T M a x w + 1 T2U_{w}(TMin_{w})=-2^{w-1}+2^{w}=2^{w-1}=TMax_{w}+1 T2Uw(TMinw)=−2w−1+2w=2w−1=TMaxw+1 —— 最小的负数映射为一个刚好在补码的正数范围之外的无符号数。
-
根据下图所示,我们能看到 T 2 U 16 ( − 12345 ) = 65563 + ( − 12345 ) = 53191 T2U_{16}(-12 345)=65 563+(-12 345)=53 191 T2U16(−12345)=65563+(−12345)=53191。
-
12 345 和 -12 345 的补码表示,以及 53 191 的无符号表示。注意后面两个数有相同的位表示。
五、扩展一个数字的位表示
一个常见的运算是在不同字长的整数之间转换,同时又保持数值不变。当然,当目标数据类型太小以至于不能表示想要的值时,这根本就是不可能的。然而,从一个较小的数据类型转换到一个较大的类型,应该总是可能的。
-
要将一个无符号数转换为一个更大的数据类型,我们只要简单地在表示的开头添加 0 这种运算被称为零扩展( zero extension ),表示原理如下:
-
原理:无符号数的零扩展。
-
定义宽度为 w w w 的位向量 u ⃗ = [ u w − 1 , u w − 2 , . . . , u 0 ] \vec{u} = [ u_{w-1} , u_{w-2} , ... , u_{0} ] u=[uw−1,uw−2,...,u0] 和宽度为 w ′ w\prime w′ 的位向量 u ⃗ ′ = [ 0 , . . . , 0 , u w − 1 , u w − 2 , . . . , u 0 ] \vec{u}\prime = [ \color{SkyBlue}0 , \color{Black}... , \color{SkyBlue}0 , \color{Black}u_{w-1} , u_{w-2} , ... , u_{0} ] u′=[0,...,0,uw−1,uw−2,...,u0] ,其中 w ′ > w w\prime > w w′>w。则 B 2 U w ( u ⃗ ) = B 2 U w ′ ( u ′ ⃗ ) B2U_{w}(\vec{u})=B2U_{w\prime}(\vec{u\prime}) B2Uw(u)=B2Uw′(u′)
-
要将一个补码数字转换为一个更大的数据类型,可以执行一个符号扩展( sign extension ),在表示中添加最高有效位的值,表示为如下原理。我们用蓝色标出符号位 x w − 1 \color{SkyBlue}x_{w-{1}} xw−1 来突出它在符号扩展中的角色。
-
原理:补码数的符号扩展。
-
定义宽度为 w w w 的位向量 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x} = [ \color{SkyBlue}x_{w-1} , \color{Black}x_{w-2} , ... , x_{0} ] x=[xw−1,xw−2,...,x0] 和宽度为 w w w 的位向量 x ⃗ ′ = [ x w − 1 , . . . , x w − 1 , x w − 1 , x w − 2 , x 0 ] \vec{x}\prime = [ \color{SkyBlue}x_{w-1} , \color{Black}... , \color{SkyBlue}x_{w-1} , \color{SkyBlue}x_{w-1} , \color{Black}x_{w-2} ,x_{0} ] x′=[xw−1,...,xw−1,xw−1,xw−2,x0] ,其中 w ′ > w w\prime > w w′>w。则 B 2 T w ( x ⃗ ) = B 2 T w ′ ( x ′ ⃗ ) B2T_{w}(\vec{x})=B2T_{w\prime}(\vec{x\prime}) B2Tw(x)=B2Tw′(x′)
六、截断数字
- 假设我们不用额外的位来扩展一个数值,而是减少表示一个数字的位数。例如下面代码中这种情况:
int x = 53191;
short sx= (short) x; /* -12345 */
int y = sx; /* -12345 */
-
当我们把 × 强制类型转换为
short
时,我们就将 32 位的int
截断为了 16 位的short
int
。 -
就像前面所看到的,这个 16 位的位模式就是 -12345 的补码表示。当我们把它强制类型转换回
int
时,符号扩展把高 16 位设置为 1,从而生成 -12345 的 32 位补码表示。 -
当将一个 w w w 位的数 x ⃗ = [ x w − 1 , x w − 2 , . . . , x 0 ] \vec{x}=[x_{w-1} , x_{w-2} , ... , x_{0}] x=[xw−1,xw−2,...,x0] 截断为一个 k k k 位数字时,我们会丢弃高 w − k w-k w−k 位,得到一个位向量 x ⃗ ′ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec{x}\prime=[ x_{k-1} , x_{k-2} , ... , x_{0} ] x′=[xk−1,xk−2,...,x0] 。截断一个数字可能会改变它的值 —— 溢出的一种形式。对于一个无符号数,我们可以很容易得出其数值结果。
-
原理:截断无符号数。
-
令 x ⃗ \vec{x} x 等于位向量 [ x w − 1 , x w − 2 , . . . , x 0 ] [x_{w-1} , x_{w-2} , ... , x_{0}] [xw−1,xw−2,...,x0] ,而 x ⃗ ′ \vec{x}\prime x′ 是将其截断为 k k k 位的结果: x ⃗ ′ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec{x}\prime=[x_{k-1} , x_{k-2} , ... , x_{0}] x′=[xk−1,xk−2,...,x0] 。令 x = B 2 U w ( x ⃗ ) x=B2U_{w}(\vec{x}) x=B2Uw(x) , x ′ = B 2 U k ( x ⃗ ′ ) x\prime=B2U_{k}(\vec{x}\prime) x′=B2Uk(x′) 。则 x ⃗ ′ = x m o d 2 k \vec{x}\prime=x \bmod 2^{k} x′=xmod2k 。该原理背后的直觉就是所有被截去的位其权重形式都为 2 i 2^{i} 2i ,其中 i ≥ k i \geq k i≥k,因此,每一个权在取模操作下结果都为零。
-
原理:截断补码数值。
-
令 x ⃗ \vec{x} x 等于位向量 [ x w − 1 , x w − 2 , . . . , x 0 ] [x_{w-1} , x_{w-2} , ... , x_{0}] [xw−1,xw−2,...,x0] ,而 x ⃗ ′ \vec{x}\prime x′ 是将其截断为 k k k 位的结果: x ⃗ ′ = [ x k − 1 , x k − 2 , . . . , x 0 ] \vec{x}\prime=[x_{k-1} , x_{k-2} , ... , x_{0}] x′=[xk−1,xk−2,...,x0] 。
-
令 x = B 2 U w ( x ⃗ ) x=B2U_{w}(\vec{x}) x=B2Uw(x) , x ′ = B 2 T k ( x ⃗ ′ ) x\prime=B2T_{k}(\vec{x}\prime) x′=B2Tk(x′) 。则 x ′ = U 2 T k ( x m o d 2 k ) x\prime=U2T_{k}(x \bmod 2^{k}) x′=U2Tk(xmod2k) 。
-
在这个公式中, x m o d 2 k x \bmod 2^{k} xmod2k 将是 0 到 2 k − 1 2^{k}-1 2k−1 之间的一个数。对其应用函数 U 2 T k U2T_{k} U2Tk ,产生的效果是把最高有效位 x k − 1 x_{k-1} xk−1 的权重从 2 k − 1 2^{k-1} 2k−1 转变为 − 2 k − 1 -2^{k-1} −2k−1。
-
举例来看,将数值 x = 53191 x=53 191 x=53191 从
int
转换为short
。由于 2 16 = 65536 ≥ x 2^{16}=65 536 \geq x 216=65536≥x ,我们有 x m o d 2 16 = x x \bmod 2^{16}=x xmod216=x 。但是,当我们把这个数转换为 16 位的补码时,我们得到 x ⃗ ′ = 53191 − 65536 = − 12345 \vec{x}\prime=53 191-65 536=-12 345 x′=53191−65536=−12345
七、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。