我还没有找到最低签名负数没有等效签名正数的原因? 为简单起见,我的意思是3位二进制数 100是-4?但我们不能在签名格式中得到积极的4,因为我们不能。它溢出来了。 那么我们怎么知道两个补码1000是-4 1000 0000是-128等等?我们没有原始正数
答案 0 :(得分:17)
考虑它的一种方法是签名的二进制补码格式通过为每个位分配2的幂,然后翻转最后2的幂的符号来工作。让我们看一下-4,例如,它表示为100.这意味着值为
-1 x 2^2 + 0 x 2^1 + 0 x 2^0
如果我们想得到这个值的正面版本,我们必须否定它才能得到
1 x 2^2 - 0 x 2^1 - 0 x 2^0
请注意,此值等于
1 x 2^2 + 0 x 2^1 + 0 x 2^0
换句话说,这个值的正常二进制表示是100.但是,我们在这里遇到麻烦,因为我们使用了带符号的二进制补码表示,这意味着我们已经专门保留了4位作为符号位。因此,当我们尝试将位模式100解释为带符号的三位二进制补码值时,它会与我们开始时的情况完全相同。比特的不足正在受到伤害。
更一般地,给定n位,其中第一位是二进制补码表示中的符号位,尝试计算-1000 ... 00将返回相同的值,因为存储大正值所需的位具有赋予它的特殊含义。
那为什么要这样呢?原因是如果你只有n位,你不能存储值-2 n - 1 到2 n - 1 ,因为有2个 n +这里有1个不同的数字,只有2 ^ n个不同的位模式。因此,排除最大正数使得可以在指定的位模式中保存所有不同的数字。
但为什么要降低高价值而不是低价值呢?这是为了保持与无符号整数的二进制兼容性。在无符号整数中,值0到2 n-1 - 1都使用标准的base-two表示法进行编码。因此,对于无符号和有符号整数完全一致,无符号整数的设计使它们与前2个 n - 1 无符号整数的位数相等,范围从0到2 n - 1 - 1,包括在内。在此之后,无符号值需要最高位来编码数字,但有符号值使用此值作为符号位。
希望这有帮助!
答案 1 :(得分:12)
-INT_MIN
是整数溢出,在C中是未定义的行为。
-INT_MIN
才能保证等于INT_MIN
。可以使用gcc
启用此功能,例如使用-fwrapv
选项。
编译器通常利用C中的整数溢出是未定义的行为来执行某些优化。依赖于包装的有符号整数溢出是不安全的。
一个众所周知的编译器优化示例如下
#define ABS(x) ((x) > 0 ? (x) : -(x))
void foo(int x){
if (ABS(x) >= 0) {
// some code
}
}
今天启用了优化选项的大多数编译器(gcc
,icc
)都会根据-INT_MIN
未定义的行为来优化测试。
答案 2 :(得分:3)
一个。 n位二进制数有多种可能性,因此我们不能代表正数和负数的相同范围。
B中。我们希望以1开头的每个数字都是负数,每个以0开头的数字都是非负数。 (不是相反的,因为我们希望在签名和未签名中同样表示正数和零。因此,0表示正数的一半,因此它们只有一个地方。
答案 3 :(得分:3)
two's complement的替代品具有此类属性,称为one's complement 在一个补码形式中,最低可能值也具有有效的正形式。
一个补码的工作原理是简单地反转数字本身的所有位
例如,我们知道0110 == 6
和一个补码1001 == -6
。使用一个补码,我们得到的正数与负数一样多。
但是位代表1111
怎么样?通过观察它,我们可以看出它是零(0000 = 0; 1111 = -0
)的“负面”形式,但这样的数字没有任何意义,并且有点浪费。
相反,我们使用两个补码,类似于一个补码,但在反转这些位后,我们加一个。因此,如果我们知道0110 = 6
,那么一个补码是1001
,而二者的补码是1001 + 1 == 1010
。使用二进制补码,我们没有“负零”,因为它会导致溢出。
另一种看待它的方式是“如果设置了最高位,则数字为负”。这意味着正范围是[0 .. 2^(bits - 1)]
,负范围是其他一切。正数与正数相同,但因为(在此格式中)零被认为是正数,负范围会被转移到[-1 .. (neg) 2^(bits - 1)]
。
让我们假设我们正在处理2位补码中的3位有符号数。那给了我们下面的表格:
BITS VALUE
000 0
001 1
010 2
011 3
100 -4
101 -3
110 -2
111 -1
你可以看到正数和负数的数量相同,只是负数不像正数那样从0开始。
答案 4 :(得分:2)
缺少的数字是0
。在数学意义上,0既不是正面也不是负面。但在二元意义上,由于0
没有负位,因此它被认为是正数。换句话说,如果你想要-128到128,就不会有0。
答案 5 :(得分:1)
因为必须计数0.整数范围[-4,-1](或等效-4,-3,-2和-1)包含4个数字,其余范围为[0,3] (或者,等效地,0,1,2和3)包含4个数字,总共8个,并且3个数字二进制数具有2个3(= 8)个可能组合的幂。
这样想。形式[-n,+ n]的任何整数范围必须具有奇数大小(2 * n + 1个整数)。无论你使用什么整数二进制表示,都会有不同数量的负数和正数,因为组合数总是偶数(幂为2)。
答案 6 :(得分:0)
那么我们怎么知道两个补码1000是-4 1000 0000是-128 等等?我们没有原始正数
你的错误是认为我们需要正数的二进制补码表示,以便计算负数的二进制补码表示。
找到负数的二进制补码的过程是:
从要表示的数字的绝对值的正常非二进制补码表示开始。因此对于-4,采用| -4 |,100的非二进制补码表示。
翻转所有位:100 - > 011(或...... 11111011,其中一些无限期地继续向左)。
添加一个:011 - > 100(或...... 11111100)
现在截断到你正在使用的位数(这消除了进位或1s的无限串)。结果,100是-4的2位补码表示。
换句话说,取两个补码表示(100)翻转位(011)并加一个(100),你现在得到| -4 |的非二进制补码表示。 1 * 2 ^ 2 + 0 * 2 ^ 1 + 0 * 2 ^ 0 = 4.因此我们知道我们从100开始的表示是-3的2位补码表示。