简体   繁体   English

二的补数-负数如何处理?

[英]Two's Complement — How are negative numbers handled?

It is my understanding that numbers are negated using the two's compliment, which to my understanding is: !num + 1. So my question is does this mean that, for variable 'foo'=1, a negated 'foo' will be the exactly the same as variable 'bar'=255. 据我了解,数字是使用两个补码取反的,据我理解是:!num +1。所以我的问题是这是否意味着对于变量'foo'= 1,否定的'foo'将是与变量'bar'= 255相同。 f we were to check if -'foo' == 'bar' or if -'foo' == 255, would we get that they are equal? 如果我们要检查-'foo'=='bar'或-'foo'== 255,我们是否会得出它们相等? I know that some languages, such as Java, keep a sign bit -- so the comparisons would yield false. 我知道某些语言(例如Java)会保留一个符号-因此比较将得出false。 What of languages that do not? 哪些语言没有呢? And I'm assuming that assembler/native machine does not have a sign bit. 我假设汇编程序/本机没有符号位。

In addition to all of this, I read about a zero flag or a carry-over flag that is set when a 'negative' number is added to another (of any sign) number. 除了所有这些,我还读到了一个零标志或一个“负”标志,该标志是在将“负”数字添加到另一个(任何符号)数字时设置的。 This flag being set whenever it is added because of the way two's complement works, 0x01 + 0xff = 0x00 (with the leading 1 truncated). 由于二进制补码的工作方式,在添加此标志时都会将其设置为0x01 + 0xff = 0x00(前导1被截断)。 What exactly is this flag used for? 该标志的作用是什么?

And my last question, for other math operations (such as multiplication), would I have to re-negate the number (so it is now positive), perform the operation, and negate the result? 还有我的最后一个问题,对于其他数学运算(例如乘法),我是否必须重新取数字(现在为正数),执行该运算并取反结果? Eg, !((!neg + 1) * pos) + 1. 例如,!((!neg + 1)* pos)+ 1。

Edit Finished the question, so feel free fire away. 编辑问题已完成,所以请放手。

Yes, in two's complement, the number x is represented as ~ x +1, where ~x is the bitwise complement of the binary numeral for x in some fixed number bits. 是的,以二进制补码形式表示,数字x表示为〜x +1,其中〜x是x在某些固定数字位中二进制数字的按位补码。 Eg, for eight bits, the binary numeral for x is 000000001, so the bitwise complement is 11111110, and adding one produces 11111111. 例如,对于八位, x的二进制数字是000000001,所以按位补码是11111110,将其相加会产生11111111。

There is no way to distinguish -1 in eight-bit two's complement from 255 in eight-bit binary (with no sign). 无法将八位二进制补码中的-1与八位二进制数中的255(无符号)区分开。 They both have the same representation in bits: 11111111. If you are using both of these numbers, you must either separately remember which one is eight-bit two's complement and which one is plain eight-bit binary or you must use more than eight bits. 它们在位上的表示相同:11111111。如果您同时使用这两个数字,则必须分别记住哪个是八位二进制数的补码,哪个是普通八位二进制数,或者必须使用八位以上。 In other words, at the raw bit level, 11111111 is just eight bits; 换句话说,在原始位级别,11111111只是八个位; it has no value until we decide how to interpret it. 它没有价值,直到我们决定如何解释它。

Java and typical other languages do not maintain a sign bit separate from the value of a number; Java和其他典型语言不会将符号位与数字值分开; the sign is part of the encoding of the number. 符号是数字编码的一部分。 Also, typical languages do not allow you to compare different types. 另外,典型的语言不允许您比较不同的类型。 If you have a two's complement x and an unsigned y , then either one must be converted to the type of the other before comparison or they must both be converted to a third type. 如果您有一个补码x和一个无符号y ,则在比较之前必须将一个转换为另一个的类型,或者必须将它们都转换为第三种类型。 Thus, if you compare x and y , and one is converted to the other, then the conversion will overflow or wrap, and you cannot expect to get the correct mathematical result. 因此,如果比较xy ,并且一个转换为另一个,则转换将溢出或换行,并且您将无法期望获得正确的数学结果。 To compare these two numbers, we might convert each of them to a wider integer, such as 32-bits, then compare. 为了比较这两个数字,我们可以将它们中的每一个转换为更大的整数(例如32位),然后进行比较。 Converting the eight-bit two's complement 11111111 to a 32-bit integer produces -1, and converting the eight-bit plain binary 11111111 to a 32-bit integer produces 255, and then the comparison reports they are unequal. 将八位二进制补码11111111转换为32位整数会产生-1,而将八位普通二进制11111111转换为32位整数会产生255,然后比较报告它们不相等。

The zero flag and the carry flag you read about are flags that are set when a comparison instruction is executed in a computer processor. 您所了解的零标志和进位标志是在计算机处理器中执行比较指令时设置的标志。 Most high-level languages do not give you direct access to these flags. 大多数高级语言都不允许您直接访问这些标志。 Many processors have an instruction with a form like this: 许多处理器的指令格式如下:

cmp a, b

That instruction subtracts b from a and discards the difference but remembers several flags that describe the subtraction: Was the result zero (zero flag)? 该指令从a减去b并丢弃差值,但记住几个描述减法的标志:结果是否为零(零标志)? Did a borrow occur (borrow flag)? 是否发生借阅(借阅标志)? Was the result negative (sign flag)? 结果是否为负(标志)? Did an overflow occur (overflow flag)? 是否发生溢出(溢出标志)?

The compare instruction requires that the two things being compared be the same type (two's complement or unsigned), but it does not care which type. 比较指令要求被比较的两个事物是同一类型(二进制补码或无符号),但是它并不关心哪种类型。 The results can be tested later by checking particular combinations of the flags depending on the type. 以后可以通过检查标志的特定组合(取决于类型)来测试结果。 That is, the information recorded in the flags can distinguish whether one two's complement number was greater than another or whether one unsigned number was greater than another, depending on what tests are made. 即,根据进行的测试,标记中记录的信息可以区分一个人的补码数是否大于另一个,或者一个无符号数是否大于另一个。 There are conditional branch instructions that test the desired flag properties. 有条件分支指令可测试所需的标志属性。

There is generally no need to “un-negate” a number to perform arithmetic operations. 通常无需“取反”数字即可执行算术运算。 Processors include arithmetic instructions that work on two's complement numbers. 处理器包括对二进制补码起作用的算术指令。 Usually the add and subtract instructions are type-agnostic, the same way the compare instruction is, but the multiply and divide instructions are not (except for some forms of multiply that return partial results). 通常,加法和减法指令与类型无关,与比较指令相同,但乘法和除法指令不是类型(除了某些返回部分结果的乘法形式)。 The add and subtract instructions can be type-agnostic because the wrapping that occurs in the arithmetic works for both two's complement and unsigned. 加法和减法指令可以是类型无关的,因为在算术中发生的换行对二进制补码和无符号数都有效。 However, that wrapping does not work for multiplication and division. 但是,该换行不适用于乘法和除法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM