This is true for all negative numbers.
f(n) = abs(n)
Because there is one more negative number than there are positive numbers for twos complement integers, f(n) = abs(n)
is valid for one more case than f(n) = n > 0 ? -n : n
solution that is the same same as f(n) = -abs(n)
. Got you by one ... :D
UPDATE
No, it is not valid for one case more as I just recognized by litb's comment ... abs(Int.Min)
will just overflow ...
I thought about using mod 2 information, too, but concluded, it does not work ... to early. If done right, it will work for all numbers except Int.Min
because this will overflow.
UPDATE
I played with it for a while, looking for a nice bit manipulation trick, but I could not find a nice one-liner, while the mod 2 solution fits in one.
f(n) = 2n(abs(n) % 2) - n + sgn(n)
In C#, this becomes the following:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
To get it working for all values, you have to replace Math.Abs()
with (n > 0) ? +n : -n
and include the calculation in an unchecked
block. Then you get even Int.Min
mapped to itself as unchecked negation does.
UPDATE
Inspired by another answer I am going to explain how the function works and how to construct such a function.
Lets start at the very beginning. The function f
is repeatedly applied to a given value n
yielding a sequence of values.
n => f(n) => f(f(n)) => f(f(f(n))) => f(f(f(f(n)))) => ...
The question demands f(f(n)) = -n
, that is two successive applications of f
negate the argument. Two further applications of f
- four in total - negate the argument again yielding n
again.
n => f(n) => -n => f(f(f(n))) => n => f(n) => ...
Now there is a obvious cycle of length four. Substituting x = f(n)
and noting that the obtained equation f(f(f(n))) = f(f(x)) = -x
holds, yields the following.
n => x => -n => -x => n => ...
So we get a cycle of length four with two numbers and the two numbers negated. If you imagine the cycle as a rectangle, negated values are located at opposite corners.
One of many solution to construct such a cycle is the following starting from n.
n => negate and subtract one
-n - 1 = -(n + 1) => add one
-n => negate and add one
n + 1 => subtract one
n
A concrete example is of such an cycle is +1 => -2 => -1 => +2 => +1
. We are almost done. Noting that the constructed cycle contains an odd positive number, its even successor, and both numbers negate, we can easily partition the integers into many such cycles (2^32
is a multiple of four) and have found a function that satisfies the conditions.
But we have a problem with zero. The cycle must contain 0 => x => 0
because zero is negated to itself. And because the cycle states already 0 => x
it follows 0 => x => 0 => x
. This is only a cycle of length two and x
is turned into itself after two applications, not into -x
. Luckily there is one case that solves the problem. If X
equals zero we obtain a cycle of length one containing only zero and we solved that problem concluding that zero is a fixed point of f
.
Done? Almost. We have 2^32
numbers, zero is a fixed point leaving 2^32 - 1
numbers, and we must partition that number into cycles of four numbers. Bad that 2^32 - 1
is not a multiple of four - there will remain three numbers not in any cycle of length four.
I will explain the remaining part of the solution using the smaller set of 3 bit signed itegers ranging from -4
to +3
. We are done with zero. We have one complete cycle +1 => -2 => -1 => +2 => +1
. Now let us construct the cycle starting at +3
.
+3 => -4 => -3 => +4 => +3
The problem that arises is that +4
is not representable as 3 bit integer. We would obtain +4
by negating -3
to +3
- what is still a valid 3 bit integer - but then adding one to +3
(binary 011
) yields 100
binary. Interpreted as unsigned integer it is +4
but we have to interpret it as signed integer -4
. So actually -4
for this example or Int.MinValue
in the general case is a second fixed point of integer arithmetic negation - 0
and Int.MinValue
are mapped to themselve. So the cycle is actually as follows.
+3 => -4 => -3 => -4 => -3
It is a cycle of length two and additionally +3
enters the cycle via -4
. In consequence -4
is correctly mapped to itself after two function applications, +3
is correctly mapped to -3
after two function applications, but -3
is erroneously mapped to itself after two function applications.
So we constructed a function that works for all integers but one. Can we do better? No, we cannot. Why? We have to construct cycles of length four and are able to cover the whole integer range up to four values. The remaining values are the two fixed points 0
and Int.MinValue
that must be mapped to themselves and two arbitrary integers x
and -x
that must be mapped to each other by two function applications.
To map x
to -x
and vice versa they must form a four cycle and they must be located at opposite corners of that cycle. In consequence 0
and Int.MinValue
have to be at opposite corners, too. This will correctly map x
and -x
but swap the two fixed points 0
and Int.MinValue
after two function applications and leave us with two failing inputs. So it is not possible to construct a function that works for all values, but we have one that works for all values except one and this is the best we can achieve.