24

In a course on algorithms and data structures at my university, I received this question:

Which integer has the same bit-pattern as his negative value?

Means: x == -x

I know that 0 works, but I suspect that the instructor was looking for some other number x. What x is it? How would you find it?

codepleb
  • 10,086
  • 14
  • 69
  • 111
  • 2
    What about `1111111111111111`? – Luiggi Mendoza Oct 24 '13 at 20:53
  • 3
    Think about how 2's complement works at the extremes – Mark Meyer Oct 24 '13 at 20:54
  • 1
    @LuiggiMendoza: That's -1, but you cannot display this in another way, if I understand this right. :) – codepleb Oct 24 '13 at 21:07
  • 3
    Java does not have unsigned integers, therefore 0 is the only solution. In C for example you could interpret the same bit pattern as a signed or unsigned integer. – lbalazscs Oct 24 '13 at 21:10
  • @lbalazscs Unsigned integers are not required. What is required for this puzzle to have an answer is 2's complement signed integers which have an asymmetric range about 0. Specifically, they have one more negative value than positive values. – RBerteig Oct 24 '13 at 23:49
  • It's not even true for C, with one's complement. Negative zero is 10000000000000000. – MSalters Oct 25 '13 at 06:58
  • Further, the [Java Language specifies](http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2) "The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units". C, on the other hand, does not specify that signed values are 2s complement. – RBerteig Oct 25 '13 at 18:23

5 Answers5

32

Integer.MIN_VALUE and Long.MIN_VALUE have no equivalent positive value and when you take the negative value of these, you get the same value.

Negative is the same as flipping all the bits and adding one. i.e.

-x = ~x + 1

So -0x80000000 = 0x7fffffff + 1 = 0x8000000

Note: Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE which is negative. This is outlined in the javadoc for this method.

Technically there are many answers and types

byte x = 0;
short x = 0;
char x = 0;
int x = 0;
int x = Integer.MIN_VALUE;
float x = 0.0f;
float x = -0.0f;
long x = 0;
long x = Long.MIN_VALUE;
double x = 0.0;
double x = -0.0;
Byte x = 0;
Short x = 0;
Character x = 0;
Integer x = 0;
Integer x = Integer.MIN_VALUE;
Float x = 0.0f;
Float x = -0.0f;
Long x = 0L;
Long x = Long.MIN_VALUE;
Double x = 0.0;
Double x = -0.0;

A similar Java Puzzler is; when is the following expression true.

x != x + 0

EDIT: Floating point has both +0.0 and -0.0. A such you might consider -0.0 a different value to 0.0 although it is the case that -0.0 == -(-0.0)

Note: Double.compare(0.0, -0.0) > 0 Note:

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 2
    @jmiserez for a course about data structures, you should not tie to a specific programming language internals. – Luiggi Mendoza Oct 24 '13 at 21:13
  • So essentially you are saying it's a bit of a trick question? – Radiodef Oct 24 '13 at 21:16
  • @jmiserez Well, if you want to be technical, 0 isn't an answer either because it isn't a negative value. – ajb Oct 24 '13 at 21:21
  • 2
    @jmiserez `int x = Integer.MIN_VALUE; if (x != 0 && x == -x)` is true. – Peter Lawrey Oct 24 '13 at 21:21
  • What I don't see in your solution: If I negate x and add +1, then it isn't the same number. As I understand his question, this should not be the point. "Is there an existing int-number, which is x == -x?" This is the whole question and in my opinion, this question could not make sense as I understand it. But I think this solution is, what he wanted from us. Thank you very much! :) – codepleb Oct 24 '13 at 21:25
  • @PeterLawrey Second question: `x` is `NaN`, or `x` is a `String`. Are there any others? – ajb Oct 24 '13 at 21:31
  • @TrudleR `~` is a `tilde`, not `-` which is negative. – Peter Lawrey Oct 24 '13 at 21:33
  • @PeterLawrey: I guess it's mostly semantics. The value of -Integer.MIN_VALUE is still Integer.MIN_VALUE, not something else (it does not change due to the limited range of an Integer). Of course the bit pattern is going to be the same. But I guess you are right then. – jmiserez Oct 24 '13 at 21:35
10

Suppose that you take the lowest possible representable number in signed two's-complement format. Let's say this number (call it x) has bit pattern 100000...0, for example. To compute -x, you first flip all the bits to get 01111...1, then add one to it. This causes a large ripple carry that results in the number 1000....0 again, which is the number that you started with. Thus you would have that x == -x. In the case of Java ints, this value is Integer.MIN_VALUE, which is -231.

You can actually figure this out mathematically. Since all numbers in signed two's-complement format are represented modulo some power of two (say, 2d), then the statement

x == -x

Really means

x == -x (mod 2d)

This means that

2x == 0 (mod 2d)

Therefore, the solutions to this problem are the set of all numbers x where 2x is 0 mod 2d. These are numbers of the form k × 2d for any integer k. Only two of these values can be represented in signed two's-complement format with d + 1 bits, namely, 0 and -2d. Therefore, the minimum possible negative number will always compare equal to its negative value.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • +1 for not forgetting 0 (although this should be obvious when thinking x==-x) – Gyro Gearless Oct 24 '13 at 21:14
  • I don't understand how `x == -x (mod 2^d) ` can go to `2x == 0 (mod 2^d)` since `-x` is in a multiplication, not an addition =\ – Luiggi Mendoza Oct 24 '13 at 21:19
  • @LuiggiMendoza add `x` to both sides of the equality??? That works in modular arithmetic. – ajb Oct 24 '13 at 21:22
  • @ajb that would be `2x == -x(mod2^d) + x`, it is not the same. – Luiggi Mendoza Oct 24 '13 at 21:23
  • 3
    @LuiggiMendoza In `x == y (mod m)`, that should be an equivalence symbol in the middle (with three horizontal dashes) instead of `==`. If you're not familiar with this, look up "Modular arithmetic" in Wikipedia. `(mod m)` isn't a modulo "operator", like `(x mod m)` would be. If `a==b (mod m)`, then `a+c == b+c (mod m)`. – ajb Oct 24 '13 at 21:29
1

For an 8 bit integer: 1000 0000 signed this is -128 while unsigned this is 128

Daniel
  • 36,610
  • 3
  • 36
  • 69
0

To look at this another way: All signed primitive integer types represent integers in the range

-2N-1 to 2N-1-1

(inclusive), where N is the number of bits. Whenever any mathematical integer operation is performed, if the mathematical result is some number Z that is outside that range ("overflow"), then the actual result will be R = Z + 2N * k, where k is some positive or negative integer chosen so that R will be in the range -2N-1 to 2N-1 - 1. So say x = -2N-1, and we compute -x. The mathematical result is Z = 2N-1, but that's out of range because Z > 2N-1-1. So to get it in range, we need to add 2N * k for some k, and k must be -1. Thus the actual result is R = 2N-1 + (2N)*(-1) = 2N-1 - 2N = -2N-1, which is the original value of x. So that's a value that makes x == -x.

Java has only signed integer types, but in languages that have unsigned types, the range for unsigned types is 0 to 2N-1, inclusive. But everything else applies in the same way.

ajb
  • 31,309
  • 3
  • 58
  • 84
0

The question, as stated, is ambiguous.

0 is of course the obvious solution, and as others have discussed there are no other solutions in Java (which is how the question is tagged).

In C, for any signed integer type, the minimum value of the given type may be a solution for some implementations. For example, given a 2's-complement representation, evaluating -INT_MIN will probably give you -INT_MIN. But in fact, the behavior of evaluating that expression is undefined due to overflow, even if you assume 2's-complement. (Wraparound semantics are very common, but are not guaranteed.) Furthermore, the C standard does not require a 2's-complement representation; it also permits 1's-complement and sign-and-magnitude, neither of which has that extra negative value.

This program:

#include <stdio.h>
#include <limits.h>
int main(void) {
    int n = INT_MIN;
    printf("%d\n%d\n", n, -n); /* Warning: Undefined behavior for -n */
}

produces this output on my system:

-2147483648
-2147483648

Operations on C unsigned types have more strictly defined behavior. This program:

#include <stdio.h>
#include <limits.h>
int main(void) {
    unsigned int n = UINT_MAX / 2 + 1;
    printf("%u\n%u\n", n, -n);
}

gives this output on a system with 32-bit int (and no padding bits):

2147483648
2147483648

and will print two identical lines of output on any conforming implementation.

C++ has the same behavior (or undefined behavior) as C in this area.

In Perl, a large integer will fall over to a floating-point representation if it's too large to be represented as an integer -- but Perl scalars are complicated, and can simultaneously store more than one representation. On my 64-bit system, this Perl program:

#!/usr/bin/perl

use strict;
use warnings;

my $n = -2.0**63;
print $n, "\n", -$n, "\n";
printf "%d\n%d\n", $n, -$n;

gives this output:

-9.22337203685478e+18
9.22337203685478e+18
-9223372036854775808
-9223372036854775808

which I'm not entirely sure I can explain myself.

Python appears to fall back to some form of extended-precision integers, so the issue of overflow doesn't arise, and so there's no numeric value that is its own negation. A number of other languages (including, I think, most Lisp dialects) do the same thing.

In Ada, an integer overflow doesn't have undefined behavior; it's required to raise an exception. This program:

with Ada.Text_IO; use Ada.Text_IO;
procedure Foo is
    N: Integer := Integer'First;
begin
    Put_Line(Integer'Image(N));
    Put_Line(Integer'Image(-N));
end Foo;

produces just one line of output:

-2147483648

and then dies with a Constraint_Error exception.

And so on, and so on, and ....

So unless the instructor is just looking for zero as the answer, it depends very much on the context.

And looking at the question, why do you assume that 0 (which is a perfectly correct and obvious answer to the question as written, and apparently is the only correct answer in Java) isn't what the instructor was looking for?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631