Cela est vrai pour tous les nombres négatifs.
f (n) = abs (n)
Parce qu'il y a un nombre négatif de plus qu'il y a de nombres positifs pour deux entiers complémentaires, f(n) = abs(n)est valable pour un cas de plus que la f(n) = n > 0 ? -n : nsolution qui est la même que f(n) = -abs(n). Je vous ai par un ...: D
MISE À JOUR
Non, ce n'est pas valable pour un cas de plus comme je viens de le reconnaître par le commentaire de litb ... abs(Int.Min)va juste déborder ...
J'ai aussi pensé à utiliser les informations du mod 2, mais j'ai conclu que cela ne fonctionne pas ... trop tôt. Si cela est fait correctement, cela fonctionnera pour tous les numéros, sauf Int.Minparce que cela débordera.
MISE À JOUR
J'ai joué avec pendant un certain temps, à la recherche d'un bon truc de manipulation, mais je n'ai pas pu trouver un joli one-liner, tandis que la solution mod 2 tient dans un.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
En C #, cela devient le suivant:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Pour le faire fonctionner pour toutes les valeurs, vous devez remplacer Math.Abs()par (n > 0) ? +n : -net inclure le calcul dans un uncheckedbloc. Ensuite, vous êtes même Int.Minmappé sur lui-même comme le fait la négation non contrôlée.
MISE À JOUR
Inspiré par une autre réponse, je vais expliquer comment fonctionne la fonction et comment construire une telle fonction.
Commençons au tout début. La fonction fest appliquée à plusieurs reprises à une valeur donnée, nce qui donne une séquence de valeurs.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n))))) => ...
La question demande f(f(n)) = -n, soit deux applications successives de fnier l'argument. Deux autres applications de f- quatre au total - annulent à nouveau l'argument n.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Maintenant, il y a un cycle évident de longueur quatre. En substituant x = f(n)et en notant que l'équation obtenue f(f(f(n))) = f(f(x)) = -xest vraie, on obtient ce qui suit.
n => x => -n => -x => n => ...
Nous obtenons donc un cycle de longueur quatre avec deux nombres et les deux nombres niés. Si vous imaginez le cycle comme un rectangle, les valeurs négatives sont situées aux coins opposés.
Une des nombreuses solutions pour construire un tel cycle est la suivante à partir de n.
n => nier et soustraire un
-n - 1 = - (n + 1) => ajouter un
-n => nier et ajouter un
n + 1 => soustraire un
n
Un exemple concret est d'un tel cycle est +1 => -2 => -1 => +2 => +1. On a presque fini. En notant que le cycle construit contient un nombre positif impair, son successeur pair et que les deux nombres sont négatifs, nous pouvons facilement partitionner les nombres entiers en plusieurs de ces cycles ( 2^32est un multiple de quatre) et avons trouvé une fonction qui satisfait les conditions.
Mais nous avons un problème avec zéro. Le cycle doit contenir 0 => x => 0parce que zéro est annulé à lui-même. Et parce que le cycle indique déjà 0 => xqu'il suit 0 => x => 0 => x. Ce n'est qu'un cycle de longueur deux et xest transformé en lui-même après deux applications, pas en -x. Heureusement, il y a un cas qui résout le problème. Si Xest égal à zéro, nous obtenons un cycle de longueur un contenant uniquement zéro et nous avons résolu ce problème en concluant que zéro est un point fixe de f.
Terminé? Presque. Nous avons des 2^32nombres, zéro est un point fixe laissant des 2^32 - 1nombres, et nous devons partitionner ce nombre en cycles de quatre nombres. Mauvais qui 2^32 - 1n'est pas un multiple de quatre - il restera trois nombres qui ne seront dans aucun cycle de longueur quatre.
Je vais expliquer la partie restante de la solution en utilisant le plus petit ensemble de itegers signés sur 3 bits allant de -4à +3. Nous en avons fini avec zéro. Nous avons un cycle complet +1 => -2 => -1 => +2 => +1. Construisons maintenant le cycle à partir de +3.
+3 => -4 => -3 => +4 => +3
Le problème qui se pose est qu'il +4n'est pas représentable comme un entier de 3 bits. Nous obtiendrions +4en niant -3à +3- ce qui est toujours un entier valide de 3 bits - mais en ajoutant ensuite un à +3(binaire 011), on obtient 100binaire. Interprété comme un entier non signé, il l'est, +4mais nous devons l'interpréter comme un entier signé -4. Donc, en fait, -4pour cet exemple ou Int.MinValuedans le cas général, il y a un deuxième point fixe de négation arithmétique entière - 0 et Int.MinValuesont mappés à eux-mêmes. Le cycle est donc en fait le suivant.
+3 => -4 => -3 => -4 => -3
C'est un cycle de longueur deux et +3entre en plus dans le cycle via -4. En conséquence -4est correctement mappé sur lui-même après deux applications de fonction, +3est correctement mappé sur -3après deux applications de fonction, mais -3est mappé par erreur sur lui-même après deux applications de fonction.
Nous avons donc construit une fonction qui fonctionne pour tous les entiers sauf un. Pouvons-nous faire mieux? Non, nous ne pouvons pas. Pourquoi? Nous devons construire des cycles de longueur quatre et pouvons couvrir toute la plage entière jusqu'à quatre valeurs. Les valeurs restantes sont les deux points fixes 0et Int.MinValuequi doivent être mappés sur eux-mêmes et deux entiers arbitraires xet -xqui doivent être mappés l'un sur l'autre par deux applications de fonction.
Pour correspondre xà -xet vice versa, ils doivent former un cycle à quatre et ils doivent être situés aux coins opposés de ce cycle. En conséquence 0et Int.MinValuedoivent également être dans des coins opposés. Cela va correctement mapper xet -xmais échanger les deux points fixes 0et Int.MinValueaprès deux applications de fonction et nous laisser avec deux entrées défaillantes. Il n'est donc pas possible de construire une fonction qui fonctionne pour toutes les valeurs, mais nous en avons une qui fonctionne pour toutes les valeurs sauf une et c'est le mieux que nous puissions obtenir.