Esto es cierto para todos los números negativos.
f (n) = abs (n)
Debido a que hay un número negativo más que números positivos para dos enteros complementarios, f(n) = abs(n)es válido para un caso más que una f(n) = n > 0 ? -n : nsolución que sea la misma que f(n) = -abs(n). Te tengo por uno ...: D
ACTUALIZAR
No, no es válido para un caso más, como acabo de reconocer por el comentario de litb ... abs(Int.Min)simplemente se desbordará ...
También pensé en usar la información de mod 2, pero concluí que no funciona ... demasiado pronto. Si se hace correctamente, funcionará para todos los números, excepto Int.Minporque se desbordará.
ACTUALIZAR
Jugué con él por un tiempo, buscando un buen truco de manipulación, pero no pude encontrar una buena línea, mientras que la solución mod 2 encaja en una.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
En C #, esto se convierte en lo siguiente:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Para conseguir que funcione para todos los valores, tiene que sustituir Math.Abs()con (n > 0) ? +n : -ne incluir el cálculo en un uncheckedbloque. Luego, incluso te Int.Minasignas a ti mismo como lo hace la negación sin control.
ACTUALIZAR
Inspirado por otra respuesta, voy a explicar cómo funciona la función y cómo construirla.
Comencemos desde el principio. La función fse aplica repetidamente a un valor dado que nproduce una secuencia de valores.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n))))) => ...
La pregunta exige f(f(n)) = -n, es decir, dos aplicaciones sucesivas de fnegar el argumento. Dos aplicaciones adicionales de f- cuatro en total - niegan el argumento nuevamente dando como resultado nnuevamente.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Ahora hay un ciclo obvio de longitud cuatro. Sustituyendo x = f(n)y observando que la ecuación obtenida se f(f(f(n))) = f(f(x)) = -xcumple, se obtiene lo siguiente.
n => x => -n => -x => n => ...
Entonces obtenemos un ciclo de longitud cuatro con dos números y los dos números negados. Si imagina el ciclo como un rectángulo, los valores negados se encuentran en las esquinas opuestas.
Una de las muchas soluciones para construir dicho ciclo es la siguiente a partir de n.
n => negar y restar uno
-n - 1 = - (n + 1) => agregar uno
-n => negar y agregar uno
n + 1 => restar uno
norte
Un ejemplo concreto es de tal ciclo es +1 => -2 => -1 => +2 => +1. Casi terminamos. Al observar que el ciclo construido contiene un número positivo impar, su sucesor par, y ambos números se niegan, podemos dividir fácilmente los enteros en muchos de estos ciclos ( 2^32es un múltiplo de cuatro) y hemos encontrado una función que satisface las condiciones.
Pero tenemos un problema con cero. El ciclo debe contener 0 => x => 0porque el cero se niega a sí mismo. Y porque el ciclo ya dice 0 => xque sigue 0 => x => 0 => x. Este es solo un ciclo de longitud dos y xse convierte en sí mismo después de dos aplicaciones, no en -x. Afortunadamente, hay un caso que resuelve el problema. Si Xes igual a cero, obtenemos un ciclo de longitud uno que contiene solo cero y resolvemos ese problema concluyendo que cero es un punto fijo de f.
¿Hecho? Casi. Tenemos 2^32números, el cero es un punto fijo que deja 2^32 - 1números, y debemos dividir ese número en ciclos de cuatro números. Malo que 2^32 - 1no es un múltiplo de cuatro: quedarán tres números que no estarán en ningún ciclo de longitud cuatro.
Explicaré la parte restante de la solución usando el conjunto más pequeño de iteradores con signo de 3 bits que van desde -4hasta +3. Hemos terminado con cero. Tenemos un ciclo completo +1 => -2 => -1 => +2 => +1. Ahora construyamos el ciclo comenzando en +3.
+3 => -4 => -3 => +4 => +3
El problema que surge es que +4no es representable como un entero de 3 bits. Obtendríamos +4negando -3a +3- lo que todavía es un número entero de 3 bits válido - pero luego sumando uno al +3(binario 011) los rendimientos 100binario. Se interpreta como un entero sin signo, +4pero tenemos que interpretarlo como un entero con signo -4. Entonces, en realidad, -4para este ejemplo o Int.MinValueen el caso general, hay un segundo punto fijo de negación aritmética de enteros, 0 y Int.MinValuese asignan a sí mismos. Entonces el ciclo es en realidad como sigue.
+3 => -4 => -3 => -4 => -3
Es un ciclo de longitud dos y además +3ingresa al ciclo a través de -4. En consecuencia, -4se asigna correctamente a sí mismo después de dos aplicaciones de función, +3se asigna correctamente -3después de dos aplicaciones de función, pero -3se asigna erróneamente a sí mismo después de dos aplicaciones de función.
Así que construimos una función que funciona para todos los enteros menos uno. ¿Podemos hacerlo mejor? No podemos. ¿Por qué? Tenemos que construir ciclos de longitud cuatro y podemos cubrir todo el rango entero hasta cuatro valores. Los valores restantes son los dos puntos fijos 0y Int.MinValueque deben asignarse a sí mismos y a dos enteros arbitrarios xy -xdeben correlacionarse entre sí mediante dos aplicaciones de función.
Para asignar xa -xy viceversa deben formar un ciclo de cuatro y deben estar ubicados en las esquinas opuestas de ese ciclo. En consecuencia 0y Int.MinValuetiene que estar en las esquinas opuestas, también. Esto asignará correctamente xy cambiará -xlos dos puntos fijos 0y Int.MinValuedespués de dos aplicaciones de función y nos dejará con dos entradas fallidas. Por lo tanto, no es posible construir una función que funcione para todos los valores, pero tenemos una que funciona para todos los valores excepto uno y esto es lo mejor que podemos lograr.