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 : n
solution 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.Min
parce 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 : -n
et inclure le calcul dans un unchecked
bloc. Ensuite, vous êtes même Int.Min
mappé 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 f
est appliquée à plusieurs reprises à une valeur donnée, n
ce 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 f
nier 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)) = -x
est 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^32
est 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 => 0
parce que zéro est annulé à lui-même. Et parce que le cycle indique déjà 0 => x
qu'il suit 0 => x => 0 => x
. Ce n'est qu'un cycle de longueur deux et x
est 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 X
est é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^32
nombres, zéro est un point fixe laissant des 2^32 - 1
nombres, et nous devons partitionner ce nombre en cycles de quatre nombres. Mauvais qui 2^32 - 1
n'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 +4
n'est pas représentable comme un entier de 3 bits. Nous obtiendrions +4
en niant -3
à +3
- ce qui est toujours un entier valide de 3 bits - mais en ajoutant ensuite un à +3
(binaire 011
), on obtient 100
binaire. Interprété comme un entier non signé, il l'est, +4
mais nous devons l'interpréter comme un entier signé -4
. Donc, en fait, -4
pour cet exemple ou Int.MinValue
dans le cas général, il y a un deuxième point fixe de négation arithmétique entière - 0
et Int.MinValue
sont 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 +3
entre en plus dans le cycle via -4
. En conséquence -4
est correctement mappé sur lui-même après deux applications de fonction, +3
est correctement mappé sur -3
après deux applications de fonction, mais -3
est 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 0
et Int.MinValue
qui doivent être mappés sur eux-mêmes et deux entiers arbitraires x
et -x
qui doivent être mappés l'un sur l'autre par deux applications de fonction.
Pour correspondre x
à -x
et vice versa, ils doivent former un cycle à quatre et ils doivent être situés aux coins opposés de ce cycle. En conséquence 0
et Int.MinValue
doivent également être dans des coins opposés. Cela va correctement mapper x
et -x
mais échanger les deux points fixes 0
et Int.MinValue
aprè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.