Questo è vero per tutti i numeri negativi.
f (n) = abs (n)
Poiché esiste un numero più negativo di quanti siano i numeri positivi per i numeri interi a due complementi, f(n) = abs(n)è valido per un caso in più rispetto alla f(n) = n > 0 ? -n : nsoluzione uguale a f(n) = -abs(n). Ti ho preso per uno ...: D
AGGIORNARE
No, non è valido per un altro caso in quanto ho appena riconosciuto dal commento di Litb ... traboccerà abs(Int.Min)...
Ho pensato di usare anche le informazioni sulla mod 2, ma ho concluso che non funziona ... troppo presto. Se fatto bene, funzionerà per tutti i numeri tranne Int.Minperché questo traboccerà.
AGGIORNARE
Ci ho giocato per un po ', cercando un bel trucco di manipolazione, ma non sono riuscito a trovare un buon one-liner, mentre la soluzione mod 2 si inserisce in uno.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
In C #, questo diventa il seguente:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Per farlo funzionare per tutti i valori, è necessario sostituirlo Math.Abs()con (n > 0) ? +n : -ne includere il calcolo in un uncheckedblocco. Quindi vieni persino Int.Minmappato su se stesso come fa la negazione non selezionata.
AGGIORNARE
Ispirato da un'altra risposta, spiegherò come funziona la funzione e come costruirla.
Cominciamo dall'inizio. La funzione fviene ripetutamente applicata a un dato valore nproducendo una sequenza di valori.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n)))) => ...
La domanda richiede f(f(n)) = -n, cioè due successive applicazioni di fnegare l'argomento. Altre due applicazioni di f- quattro in totale - annullano nuovamente l'argomentazione n.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Ora c'è un ovvio ciclo di lunghezza quattro. Sostituendo x = f(n)e notando che l'equazione ottenuta f(f(f(n))) = f(f(x)) = -xvale, si ottiene quanto segue.
n => x => -n => -x => n => ...
Quindi otteniamo un ciclo di lunghezza quattro con due numeri e i due numeri negati. Se immagini il ciclo come un rettangolo, i valori negati si trovano agli angoli opposti.
Una delle tante soluzioni per costruire un tale ciclo è la seguente a partire da n.
n => annulla e sottrai uno
-n - 1 = - (n + 1) => aggiungi uno
-n => annulla e aggiungi uno
n + 1 => sottrai uno
n
Un esempio concreto è di tale ciclo +1 => -2 => -1 => +2 => +1. Abbiamo quasi finito. Notando che il ciclo costruito contiene un numero positivo dispari, il suo successore pari ed entrambi i numeri negano, possiamo facilmente suddividere gli interi in molti di questi cicli ( 2^32è un multiplo di quattro) e abbiamo trovato una funzione che soddisfa le condizioni.
Ma abbiamo un problema con zero. Il ciclo deve contenere 0 => x => 0perché zero è negato a se stesso. E poiché il ciclo afferma già 0 => xsegue 0 => x => 0 => x. Questo è solo un ciclo di lunghezza due e xsi trasforma in se stesso dopo due applicazioni, non in -x. Fortunatamente c'è un caso che risolve il problema. Se è Xuguale a zero otteniamo un ciclo di lunghezza uno contenente solo zero e abbiamo risolto il problema concludendo che zero è un punto fisso di f.
Fatto? Quasi. Abbiamo 2^32numeri, zero è un punto fisso che lascia 2^32 - 1numeri e dobbiamo suddividere quel numero in cicli di quattro numeri. Bad che 2^32 - 1non è un multiplo di quattro - rimarranno tre numeri non in nessun ciclo di lunghezza quattro.
Spiegherò la parte rimanente della soluzione usando l'insieme più piccolo di iteger con firma a 3 bit che vanno da -4a +3. Abbiamo finito con zero. Abbiamo un ciclo completo +1 => -2 => -1 => +2 => +1. Ora costruiamo il ciclo a partire da +3.
+3 => -4 => -3 => +4 => +3
Il problema che si pone è che +4non è rappresentabile come numero intero a 3 bit. Otterremmo +4negando -3a +3- quello che è ancora un po '3 intero valido - ma poi l'aggiunta di uno a +3(binario 011) produce 100binario. Interpretato come intero senza segno, +4ma dobbiamo interpretarlo come intero con segno -4. Quindi in realtà -4per questo esempio o Int.MinValuenel caso generale è un secondo punto fisso di negazione aritmetica intera - 0 e Int.MinValuesono mappati su loro stessi. Quindi il ciclo è in realtà il seguente.
+3 => -4 => -3 => -4 => -3
È un ciclo di lunghezza due ed +3entra inoltre nel ciclo tramite -4. Di conseguenza, -4viene correttamente mappato su se stesso dopo due applicazioni, +3viene correttamente mappato su -3due applicazioni, ma -3viene erroneamente mappato su se stesso dopo due applicazioni.
Quindi abbiamo costruito una funzione che funziona per tutti gli interi tranne uno. Possiamo fare di meglio? No, non possiamo. Perché? Dobbiamo costruire cicli di lunghezza quattro e siamo in grado di coprire l'intero intervallo intero fino a quattro valori. I valori rimanenti sono i due punti fissi 0e Int.MinValueche devono essere mappati su se stessi e due numeri interi arbitrari xe -xche devono essere mappati tra loro da due applicazioni di funzione.
Per mappare xa -xe viceversa devono formare un ciclo a quattro e devono essere posizionati in angoli opposti di tale ciclo. Di conseguenza 0e Int.MinValueanche agli angoli opposti. Ciò mappare correttamente xe -xma scambiare i due punti fissi 0e Int.MinValuedopo due applicazioni funzionali e lasciarli con due ingressi fallimento. Quindi non è possibile costruire una funzione che funzioni per tutti i valori, ma ne abbiamo una che funziona per tutti i valori tranne uno e questo è il meglio che possiamo ottenere.