Dies gilt für alle negativen Zahlen.
f (n) = abs (n)
Da es eine negative Zahl mehr gibt als positive Zahlen für zwei komplementäre Ganzzahlen, f(n) = abs(n)
gilt dies für einen Fall mehr als für eine f(n) = n > 0 ? -n : n
Lösung, die dieselbe ist wie f(n) = -abs(n)
. Habe dich um eins ...: D.
AKTUALISIEREN
Nein, es ist nicht mehr für einen Fall gültig, wie ich gerade durch Litbs Kommentar erkannt habe ... abs(Int.Min)
wird einfach überlaufen ...
Ich habe auch darüber nachgedacht, Mod 2-Informationen zu verwenden, bin aber zu dem Schluss gekommen, dass es nicht funktioniert ... zu früh. Wenn es richtig gemacht wird, funktioniert es für alle Zahlen, außer Int.Min
weil dies überläuft.
AKTUALISIEREN
Ich habe eine Weile damit gespielt und nach einem netten Manipulationstrick gesucht, aber ich konnte keinen schönen Einzeiler finden, während die Mod 2-Lösung in einen passt.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
In C # wird dies wie folgt:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Um es für alle Werte arbeitet, müssen Sie ersetzen Math.Abs()
mit (n > 0) ? +n : -n
und die Berechnung in einem Include - unchecked
Block. Dann werden Sie sogar Int.Min
auf sich selbst abgebildet, wie dies bei ungeprüfter Negation der Fall ist.
AKTUALISIEREN
Inspiriert von einer anderen Antwort werde ich erklären, wie die Funktion funktioniert und wie eine solche Funktion aufgebaut wird.
Beginnen wir ganz am Anfang. Die Funktion f
wird wiederholt auf einen bestimmten Wert angewendet, n
wodurch eine Folge von Werten erhalten wird.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (n ())) => ...
Die Frage verlangt f(f(n)) = -n
, dass zwei aufeinanderfolgende Anwendungen f
das Argument negieren. Zwei weitere Anträge von f
- insgesamt vier - negieren das Argument erneut und ergeben n
erneut.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Jetzt gibt es einen offensichtlichen Zyklus der Länge vier. Das Ersetzen x = f(n)
und Feststellen, dass die erhaltene Gleichung f(f(f(n))) = f(f(x)) = -x
gilt, ergibt Folgendes.
n => x => -n => -x => n => ...
Wir erhalten also einen Zyklus der Länge vier mit zwei Zahlen und den beiden negierten Zahlen. Wenn Sie sich den Zyklus als Rechteck vorstellen, befinden sich negierte Werte an gegenüberliegenden Ecken.
Eine von vielen Lösungen zur Konstruktion eines solchen Zyklus ist die folgende ab n.
n => negiere und subtrahiere eins
-n - 1 = - (n + 1) => addiere eins
-n => negiere und füge eins hinzu
n + 1 => subtrahiere eins
n
Ein konkretes Beispiel ist ein solcher Zyklus +1 => -2 => -1 => +2 => +1
. Wir sind fast fertig. Wenn wir feststellen, dass der konstruierte Zyklus eine ungerade positive Zahl enthält, sein gerader Nachfolger und beide Zahlen negieren, können wir die ganzen Zahlen leicht in viele solcher Zyklen unterteilen ( 2^32
ist ein Vielfaches von vier) und haben eine Funktion gefunden, die die Bedingungen erfüllt.
Aber wir haben ein Problem mit Null. Der Zyklus muss enthalten, 0 => x => 0
da Null für sich selbst negiert wird. Und weil der Zyklus schon sagt 0 => x
, folgt er 0 => x => 0 => x
. Dies ist nur ein Zyklus der Länge zwei und x
wird nach zwei Anwendungen in sich selbst umgewandelt, nicht in -x
. Glücklicherweise gibt es einen Fall, der das Problem löst. Wenn X
gleich Null ist, erhalten wir einen Zyklus der Länge Eins, der nur Null enthält, und wir haben dieses Problem gelöst, indem wir daraus geschlossen haben, dass Null ein fester Punkt von ist f
.
Erledigt? Fast. Wir haben 2^32
Zahlen, Null ist ein fester Punkt, der 2^32 - 1
Zahlen hinterlässt , und wir müssen diese Zahl in Zyklen von vier Zahlen aufteilen. Schlecht, das 2^32 - 1
ist kein Vielfaches von vier - es bleiben drei Zahlen in keinem Zyklus der Länge vier.
Ich werde den verbleibenden Teil der Lösung anhand des kleineren Satzes von 3-Bit-vorzeichenbehafteten Itegern von -4
bis erklären +3
. Wir sind mit Null fertig. Wir haben einen vollständigen Zyklus +1 => -2 => -1 => +2 => +1
. Nun konstruieren wir den Zyklus ab +3
.
+3 => -4 => -3 => +4 => +3
Das auftretende Problem besteht darin, dass +4
es nicht als 3-Bit-Ganzzahl dargestellt werden kann. Wir würden +4
durch Negieren -3
auf +3
- was immer noch eine gültige 3-Bit-Ganzzahl ist - erhalten, aber dann addieren wir eine zu +3
(binär 011
) ergibt 100
binär. Als vorzeichenlose Ganzzahl +4
interpretiert ist es, aber wir müssen es als vorzeichenbehaftete Ganzzahl interpretieren -4
. Tatsächlich ist also -4
für dieses Beispiel oder Int.MinValue
im allgemeinen Fall ein zweiter fester Punkt der ganzzahligen arithmetischen Negation - 0
und Int.MinValue
werden auf sich selbst abgebildet. Der Zyklus ist also tatsächlich wie folgt.
+3 => -4 => -3 => -4 => -3
Es ist ein Zyklus der Länge zwei und +3
tritt zusätzlich über in den Zyklus ein -4
. Infolgedessen -4
wird es nach zwei Funktionsanwendungen korrekt auf sich selbst abgebildet, wird nach zwei Funktionsanwendungen korrekt auf sich selbst +3
abgebildet, wird jedoch -3
nach zwei Funktionsanwendungen -3
fälschlicherweise auf sich selbst abgebildet.
Also haben wir eine Funktion konstruiert, die für alle ganzen Zahlen außer einer funktioniert. Können wir es besser machen? Nein Wir können nicht. Warum? Wir müssen Zyklen der Länge vier konstruieren und können den gesamten ganzzahligen Bereich bis zu vier Werten abdecken. Die übrigen Werte sind die beiden Fixpunkte 0
und Int.MinValue
das muss sich selbst zugeordnet werden und zwei beliebige ganze Zahlen x
und -x
das muss durch zwei Funktionsanwendungen aufeinander abgebildet werden.
Zur Karte x
zu -x
und umgekehrt , sie müssen einen Cyclus bilden vier , und sie müssen an gegenüberliegenden Ecken des Zyklus befinden. In der Folge 0
und Int.MinValue
müssen auch an gegenüberliegenden Ecken sein. Dadurch werden die beiden Fixpunkte und nach zwei Funktionsanwendungen korrekt zugeordnet x
und -x
ausgetauscht, und es verbleiben zwei fehlerhafte Eingaben. Es ist also nicht möglich, eine Funktion zu konstruieren, die für alle Werte funktioniert, aber wir haben eine, die für alle Werte außer einem funktioniert, und dies ist das Beste, was wir erreichen können.0
Int.MinValue