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 : nLö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.Minweil 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 : -nund die Berechnung in einem Include - uncheckedBlock. Dann werden Sie sogar Int.Minauf 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 fwird wiederholt auf einen bestimmten Wert angewendet, nwodurch 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 fdas Argument negieren. Zwei weitere Anträge von f- insgesamt vier - negieren das Argument erneut und ergeben nerneut.
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)) = -xgilt, 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^32ist 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 => 0da 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 xwird nach zwei Anwendungen in sich selbst umgewandelt, nicht in -x. Glücklicherweise gibt es einen Fall, der das Problem löst. Wenn Xgleich 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^32Zahlen, Null ist ein fester Punkt, der 2^32 - 1Zahlen hinterlässt , und wir müssen diese Zahl in Zyklen von vier Zahlen aufteilen. Schlecht, das 2^32 - 1ist 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 -4bis 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 +4es nicht als 3-Bit-Ganzzahl dargestellt werden kann. Wir würden +4durch Negieren -3auf +3- was immer noch eine gültige 3-Bit-Ganzzahl ist - erhalten, aber dann addieren wir eine zu +3(binär 011) ergibt 100binär. Als vorzeichenlose Ganzzahl +4interpretiert ist es, aber wir müssen es als vorzeichenbehaftete Ganzzahl interpretieren -4. Tatsächlich ist also -4für dieses Beispiel oder Int.MinValueim allgemeinen Fall ein zweiter fester Punkt der ganzzahligen arithmetischen Negation - 0 und Int.MinValuewerden 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 +3tritt zusätzlich über in den Zyklus ein -4. Infolgedessen -4wird es nach zwei Funktionsanwendungen korrekt auf sich selbst abgebildet, wird nach zwei Funktionsanwendungen korrekt auf sich selbst +3abgebildet, wird jedoch -3nach zwei Funktionsanwendungen -3fä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 0und Int.MinValuedas muss sich selbst zugeordnet werden und zwei beliebige ganze Zahlen xund -xdas muss durch zwei Funktionsanwendungen aufeinander abgebildet werden.
Zur Karte xzu -xund umgekehrt , sie müssen einen Cyclus bilden vier , und sie müssen an gegenüberliegenden Ecken des Zyklus befinden. In der Folge 0und Int.MinValuemüssen auch an gegenüberliegenden Ecken sein. Dadurch werden die beiden Fixpunkte und nach zwei Funktionsanwendungen korrekt zugeordnet xund -xausgetauscht, 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.0Int.MinValue