2

I'm in a C++ programming class, and I am taking a practice exam. One of the questions is "In standard mathematics, 0 is the only value for which x = -x. However, in C, there are two such values. What are they?"

I know one of them is 0. What could the other be? The lowest possible negative number? Thanks!

Tim
  • 41,901
  • 18
  • 127
  • 145
user3504959
  • 71
  • 1
  • 3
  • 3
    Sounds like you already answered your question. – Mysticial May 08 '14 at 19:37
  • It depends on the computer architecture. – pmg May 08 '14 at 19:39
  • 5
    `-INT_MIN` is actually undefined in standard C on 2-complement machine, although you are likely to get `INT_MIN` back in practical implementations. `(unsigned int)INT_MIN` would be more valid. – zch May 08 '14 at 19:40
  • Having 2^n binary representations and two's complement: One number is the zero the other the minimum, as you answered it yourself –  May 08 '14 at 19:42
  • If you really wanted to nitpick, for signed integers, 0 is the only one. Because negating the other one is integer overflow - undefined behavior. – Mysticial May 08 '14 at 19:43
  • 5
    I hate it that exams often make such questions even though it's undefined behavior. Especially for tests one should stay standards compliant or you don't have to wonder if people later got various occasions of undefined behavior in their code. – AliciaBytes May 08 '14 at 19:45
  • Or at the very least make a note above such questions that it's formally undefined behaviour and they're asking for one common implementation. – AliciaBytes May 08 '14 at 19:47
  • There might be even more. For example, `(unsigned long)LONG_MIN` and `(unsigned long long)LLONG_MIN` might be distinct. – zch May 08 '14 at 19:57

5 Answers5

3

However, in C, there are two such values. What are they?

This statement is wrong.

For int values, the only value x == -x is x = 0.

-INT_MIN cannot be computed as -INT_MIN invokes undefined behavior.

Note that for floating points (IEEE-754), there are two distinct values for 0.0, +0.0 and -0.0 and this expression yields 1:

 0.0 == -0.0
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    @user2864740 IEEE-754 guarantees `0.0 == -0.0` is `1`. – ouah May 08 '14 at 19:48
  • What you mean may be right, but you are contradicting yourself. The fact that `-INT_MIN` is undefined in standard C (assuming `INT_MIN < -INT_MAX`) means that for `int` values, whether there are values for which `x == -x` evaluates as true other than `0` is a question not answered by the standard. There is no requirement that the only value for `x` to make `x == -x` evaluate as true is `0`. –  May 08 '14 at 19:56
  • @hvd The requirement is implicit, can you exhibit a possible implementation where `x == -x` is true for a value different than `0` or `-0`? – ouah May 08 '14 at 20:00
  • 2
    @ouah Sure. Some implementations document the behaviour of `-INT_MIN` as an extension. That's perfectly valid. –  May 08 '14 at 20:01
  • 1
    @hvd the fact that some implementation would extend the language won't make an invalid program valid. My point is no strictly conforming program can have `x == -x` true for an `int` value different than `0` or `-0`. – ouah May 08 '14 at 20:08
  • But that's not what you said. You say that when `x == INT_MIN`, `x == -x` is not true. All that can safely be said is that when `x == INT_MIN`, `x == -x` is not required to be true. (I did start my comment with "What you mean may be right".) –  May 08 '14 at 20:11
2

The two values (at least on my machine) are: -2147483648 and 0.

This can be demonstrated with a small test program:

#include <limits.h>
#include <stdio.h>

int main(){
    int i;
    for (i = INT_MIN; i < INT_MAX; i++) {
        if (i == -i) printf("%d\n", i);
    }

    return 0;
}

What is actually going on here is caused by the representation of signed integers using two's complement:

The two's complement of the minimum number in the range will not have the desired effect of negating the number. For example, the two's complement of −128 in an 8-bit system results in the same binary number. This is because a positive value of 128 cannot be represented with an 8-bit signed binary numeral.


All that said, however, as others have mentioned this behavior may be platform and architecture dependent. It may be useful for educational purposes but I would not write a program that depends on any of this behavior.

Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
  • 1
    You are not testing `INT_MAX`. I suggest a further test after the loop :) – pmg May 08 '14 at 19:41
  • You could also make it `int main(void)` and add a final (redundant for C99) `return 0;` – pmg May 08 '14 at 19:47
  • This program invokes undefined behavior. `-INT_MIN` can yield `INT_MIN` in one implementation, crash in another implementation and yield `42` in another. – ouah May 08 '14 at 19:50
  • 3
    Now your test ( `i <= INT_MAX` ) is always true – pmg May 08 '14 at 19:54
  • @pmg and `INT_MAX + 1` also invokes undefined behavior – ouah May 08 '14 at 19:56
  • Others already commented on the undefined behaviour, so I'll just note another tricky bit. You now got an infinite loop since all ints will be <= intmax. To really make it work you gotta loop over a bigger type (long/ long long) and then cast to int for x == -x – AliciaBytes May 08 '14 at 19:56
  • @RaphaelMiedl: How do you know that `long` or `long long` is wider than `int`? It typically is, but it's not guaranteed; all three types could be 64 bits, for example. – Keith Thompson May 08 '14 at 19:58
  • @ouah: I never suggested `INT_MAX + 1`; what I suggested was a further test after the loop ... when the value of `i` is `INT_MAX` – pmg May 08 '14 at 20:01
  • @KeithThompson I know, that small program is tricky, you'd first have to compare the int max with the max for long (or long long) to really make sure that it's bigger. At least they are guaranteed to not be smaller or you couldn't even safely do that comparison. – AliciaBytes May 08 '14 at 20:02
  • @pmg I was not implying you suggested it; I mentioned that with `i <= INT_MAX; i++` there was another undefined behavior invocation. – ouah May 08 '14 at 20:05
  • @pmg like we said already, you'd have to first check if long/long long are really bigger than int, then loop over them up to int_max and cast to int inside the loop. It's a tricky little program that is harder to do right than it might first seem. – AliciaBytes May 08 '14 at 20:08
1

C allows three signed integer encodings:

  • two's complement
  • one's complement
  • sign/magnitude

Though all but the most esoteric or antique architectures use two's complement (related question).

Two's Complement

Take a simplified example of a 2 bit integer range -2 to 1. To change the sign in two'd complement you invert the bits and add one. So:

n   invert  +1(-n)
00    11    00  ---  0 == -0
01    10    11
10    01    10  --- -2 == -2
11    00    01

One's Complement

For one's complement, the bits are simply inverted and the ranbe is -1 to +1.

n   invert(-n)
00    11  
01    10  
10    01  
11    00  

Here there there are two encodings for zero (-0 and +0), so there are not values for which n == -n

Sign/magnitude

In sign/magnitude, the sign bit changes:

n   !sign(-n)
00    10  
01    11  
10    00  
11    01

And again there are no values for n == -n (and again also two encodings for zero).

Community
  • 1
  • 1
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • 1
    Surely the C standard requires that `0 == -0` even if they have different representations - does it not? – sepp2k May 08 '14 at 21:12
  • @sepp2k: Yes that is perhaps true, but the stored bit patterns are not the same. I would guess that a machine that used one's complement would perform arithmetic using a [complementing subtractor](http://en.wikipedia.org/wiki/Ones'_complement#Avoiding_negative_zero) rather than an adder used in 2's complement ALU's, this avoids the generation -0 as a result of arithmetic operations, so the value does not normally occur. – Clifford May 08 '14 at 21:32
0

It depends on the architecture. If negative numbers are represented as 2's complements, then the smallest number would qualify for x==-x. Other than that, you have zero.

HelloWorld123456789
  • 5,299
  • 3
  • 23
  • 33
  • The fact that a particular system uses a 2's complement *representation* does not directly imply anything about the behavior of operations. A conforming implementation could use 2's complement and terminate a program that tries to compute `-INT_MIN`. – Keith Thompson May 08 '14 at 20:00
  • You guys are talking about undefined behavior. But what is undefined about `-INT_MIN`? – HelloWorld123456789 May 08 '14 at 20:02
  • -INT_MIN is 1 bigger than INT_MAX in two's complement and therefore can't be represented. You got an integer overflow and the standard doesn't say what happens in that case, so anything can really happen, you got undefined behavior. – AliciaBytes May 08 '14 at 20:05
  • @RaphaelMiedl So you're saying if I add `1234567890` with `1234567890`, the program may crash? – HelloWorld123456789 May 08 '14 at 20:09
  • The thing is according to the c standard when it doesn't define a behaviour, compilers can do whatever they want. Crash, do what you expected, delet your files... So formally, yes it can. – AliciaBytes May 08 '14 at 20:12
  • Many people me included therefore try to stay as far away from undefined behaviour as we can, we don't like the compiler to be allowed to do whatever it wants. That doesn't mean that compilers are evil, just that we're trying to be on the safe side. Better safe than sorry like they say. – AliciaBytes May 08 '14 at 20:14
-3

It's true that in c there ate two numbers which are x==-x . One is 0==-0 (integers) . Second is 0.0==-0.0 (floating values) . In c integers and floating values are different.

Adarsh Sojitra
  • 2,059
  • 1
  • 27
  • 50
  • Just to put some info to the downvotes, if you'd argue this way than you'd have way more than the two values in the question, think about 0L and -0L or 0.0f and -0.0f, you got various different types for numbers and it'd work for all of them... – AliciaBytes May 08 '14 at 20:23