Isso é verdade para todos os números negativos.
f (n) = abs (n)
Como há mais um número negativo do que números positivos para dois números inteiros de complemento, f(n) = abs(n)é válido para mais um caso que a f(n) = n > 0 ? -n : nsolução que é a mesma que f(n) = -abs(n). Peguei você por um ...: D
ATUALIZAR
Não, não é válido para mais um caso, pois acabei de reconhecer pelo comentário do litb ... abs(Int.Min)apenas transbordará ...
Também pensei em usar as informações do mod 2, mas concluí que elas não funcionam ... até cedo. Se bem feito, funcionará para todos os números, exceto Int.Minporque isso excederá.
ATUALIZAR
Eu brinquei com ele por um tempo, procurando um bom truque de manipulação, mas não consegui encontrar um bom one-liner, enquanto a solução mod 2 se encaixa em um.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
Em C #, isso se torna o seguinte:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Para fazê-lo funcionar para todos os valores, você tem que substituir Math.Abs()com (n > 0) ? +n : -ne incluir o cálculo em um uncheckedbloco. Então você é Int.Minmapeado para si mesmo como a negação desmarcada.
ATUALIZAR
Inspirado por outra resposta, vou explicar como a função funciona e como construí-la.
Vamos começar do começo. A função fé aplicada repetidamente a um determinado valor, nproduzindo uma sequência de valores.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n)))) => ...
A pergunta exige f(f(n)) = -n, ou seja, duas aplicações sucessivas de fnegar o argumento. Duas outras aplicações f- quatro no total - negam que o argumento volte a render-se nnovamente.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Agora há um ciclo óbvio de comprimento quatro. Substituindo x = f(n)e observando que a equação obtida se f(f(f(n))) = f(f(x)) = -xmantém, produz o seguinte.
n => x => -n => -x => n => ...
Então, temos um ciclo de comprimento quatro com dois números e os dois números negados. Se você imaginar o ciclo como um retângulo, os valores negativos estão localizados em cantos opostos.
Uma das muitas soluções para construir esse ciclo é a seguinte, partindo de n.
n => nega e subtrai um
-n - 1 = - (n + 1) => adicione um
-n => negue e adicione um
n + 1 => subtrai um
n
Um exemplo concreto é esse ciclo +1 => -2 => -1 => +2 => +1. Estamos quase terminando. Observando que o ciclo construído contém um número positivo ímpar, seu sucessor par e ambos os números negam, podemos facilmente dividir os números inteiros em muitos desses ciclos ( 2^32é um múltiplo de quatro) e descobrimos uma função que satisfaz as condições.
Mas temos um problema com zero. O ciclo deve conter 0 => x => 0porque o zero é negado para si mesmo. E porque o ciclo já indica 0 => xa seguir 0 => x => 0 => x. Este é apenas um ciclo de comprimento dois e xé transformado em si mesmo após duas aplicações, não em -x. Felizmente, há um caso que resolve o problema. Se Xigual a zero, obtemos um ciclo de comprimento um contendo apenas zero e resolvemos esse problema concluindo que o zero é um ponto fixo de f.
Feito? Quase. Temos 2^32números, zero é um ponto fixo que deixa 2^32 - 1números e devemos particionar esse número em ciclos de quatro números. Ruim que 2^32 - 1não é múltiplo de quatro - restarão três números que não estão em nenhum ciclo de comprimento quatro.
Explicarei a parte restante da solução usando o conjunto menor de itegers assinados de 3 bits, que variam de -4até +3. Terminamos com zero. Temos um ciclo completo +1 => -2 => -1 => +2 => +1. Agora vamos construir o ciclo começando em +3.
+3 => -4 => -3 => +4 => +3
O problema que surge é que +4não é representável como número inteiro de 3 bits. Nós +4obteríamos negando -3a +3- o que ainda é um número inteiro válido de 3 bits - mas adicionando um a +3(binário 011) produz 100binário. Interpretado como número inteiro não assinado, +4mas temos que interpretá-lo como número inteiro assinado -4. Portanto, na verdade, -4para este exemplo ou Int.MinValuepara o caso geral, existe um segundo ponto fixo de negação aritmética inteira - 0 e Int.MinValuesão mapeados para eles. Portanto, o ciclo é realmente o seguinte.
+3 => -4 => -3 => -4 => -3
É um ciclo de duração dois e, adicionalmente, +3entra no ciclo via -4. Em conseqüência, -4é corretamente mapeado para si mesmo após duas aplicações de funções, +3é corretamente mapeado para -3após duas aplicações de funções, mas -3é erroneamente mapeado para si mesmo após duas aplicações de funções.
Então construímos uma função que funciona para todos os números inteiros, exceto um. Podemos fazer melhor? Não nós não podemos. Por quê? Temos que construir ciclos de comprimento quatro e somos capazes de cobrir todo o intervalo inteiro até quatro valores. Os valores restantes são os dois pontos fixos 0e Int.MinValuedevem ser mapeados para si mesmos e dois números inteiros arbitrários xe -xque devem ser mapeados entre si por dois aplicativos de função.
Para mapear xa -xe vice-versa, devem formar um ciclo de quatro e que devem estar localizados em cantos opostos desse ciclo. Em conseqüência, 0e Int.MinValuetambém deve estar em cantos opostos. Isto irá mapear corretamente xe -xmas trocar os dois pontos fixos 0e Int.MinValueapós duas aplicações de função e deixar-nos com duas entradas de falha. Portanto, não é possível construir uma função que funcione para todos os valores, mas temos uma que funcione para todos os valores, exceto um, e isso é o melhor que podemos alcançar.