Ini berlaku untuk semua angka negatif.
f (n) = abs (n)
Karena ada satu angka lebih negatif daripada angka positif untuk dua integer komplemen, f(n) = abs(n)
valid untuk satu kasus lebih dari f(n) = n > 0 ? -n : n
solusi yang sama dengan f(n) = -abs(n)
. Punya satu per satu ...: D
MEMPERBARUI
Tidak, itu tidak berlaku untuk satu kasus lagi karena saya baru saja dikenali oleh komentar litb ... abs(Int.Min)
hanya akan meluap ...
Saya berpikir tentang menggunakan informasi mod 2 juga, tetapi menyimpulkan, itu tidak berfungsi ... untuk awal. Jika dilakukan dengan benar, ini akan berfungsi untuk semua angka kecuali Int.Min
karena ini akan meluap.
MEMPERBARUI
Saya bermain dengannya sebentar, mencari trik manipulasi bit yang bagus, tetapi saya tidak dapat menemukan satu-liner yang bagus, sedangkan solusi mod 2 cocok untuk satu.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
Di C #, ini menjadi yang berikut:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Untuk membuatnya berfungsi untuk semua nilai, Anda harus mengganti Math.Abs()
dengan (n > 0) ? +n : -n
dan memasukkan perhitungan dalam satu unchecked
blok. Kemudian Anda bahkan Int.Min
dipetakan ke dirinya sendiri seperti halnya negasi yang tidak terkendali.
MEMPERBARUI
Terinspirasi oleh jawaban lain saya akan menjelaskan bagaimana fungsi bekerja dan bagaimana membangun fungsi seperti itu.
Mari kita mulai dari awal. Fungsi f
ini berulang kali diterapkan pada nilai yang diberikan n
menghasilkan urutan nilai.
n => f (n) => f (f (n)) => f (f (f (n)))) => f (f (f (f (f (n)))))) => ...
Pertanyaannya menuntut f(f(n)) = -n
, yaitu dua aplikasi berturut-turut f
meniadakan argumen. Dua aplikasi lebih lanjut dari f
- total empat - meniadakan argumen lagi menghasilkan n
lagi.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Sekarang ada siklus panjang empat yang jelas. Mengganti x = f(n)
dan mencatat bahwa persamaan yang diperoleh f(f(f(n))) = f(f(x)) = -x
berlaku, menghasilkan yang berikut.
n => x => -n => -x => n => ...
Jadi kita mendapatkan siklus panjang empat dengan dua angka dan dua angka dinegasikan. Jika Anda membayangkan siklus sebagai persegi panjang, nilai yang dinegasikan terletak di sudut yang berlawanan.
Salah satu solusi untuk membangun siklus seperti itu adalah yang berikut dimulai dari n.
n => meniadakan dan kurangi satu
-n - 1 = - (n +1) => tambahkan satu
-n => negate dan tambahkan satu
n +1 => kurangi satu
n
Contoh konkret dari siklus semacam itu adalah +1 => -2 => -1 => +2 => +1
. Kami hampir selesai. Memperhatikan bahwa siklus yang dikonstruksi mengandung bilangan positif ganjil, bahkan penggantinya, dan kedua bilangan tersebut meniadakan, kita dapat dengan mudah mempartisi bilangan bulat menjadi banyak siklus semacam itu ( 2^32
merupakan kelipatan empat) dan telah menemukan fungsi yang memenuhi kondisi.
Tetapi kami memiliki masalah dengan nol. Siklus harus mengandung 0 => x => 0
karena nol dinegasikan ke dirinya sendiri. Dan karena siklus menyatakan sudah 0 => x
mengikuti 0 => x => 0 => x
. Ini hanya siklus panjang dua dan x
diubah menjadi dirinya sendiri setelah dua aplikasi, bukan menjadi -x
. Untungnya ada satu kasus yang menyelesaikan masalah. Jika X
sama dengan nol kita memperoleh siklus panjang yang hanya mengandung nol dan kita memecahkan masalah itu dengan menyimpulkan bahwa nol adalah titik tetap f
.
Selesai? Hampir. Kami memiliki 2^32
angka, nol adalah angka tetap yang meninggalkan titik 2^32 - 1
, dan kami harus mempartisi angka itu menjadi siklus empat angka. Buruk itu 2^32 - 1
bukan kelipatan empat - akan tetap ada tiga angka tidak dalam siklus dengan panjang empat.
Saya akan menjelaskan bagian yang tersisa dari solusi menggunakan set yang lebih kecil dari 3 bit yang ditandatangani mulai dari -4
ke +3
. Kita selesai dengan nol. Kami memiliki satu siklus lengkap +1 => -2 => -1 => +2 => +1
. Sekarang mari kita buat siklus mulai dari +3
.
+3 => -4 => -3 => +4 => +3
Masalah yang muncul adalah yang +4
tidak direpresentasikan sebagai integer 3 bit. Kami akan memperoleh +4
dengan meniadakan -3
ke +3
- apa yang masih merupakan integer 3 bit yang valid - tetapi kemudian menambahkan satu ke +3
(biner 011
) menghasilkan 100
biner. Ditafsirkan sebagai bilangan bulat yang tidak ditandatangani, +4
tetapi kita harus menafsirkannya sebagai bilangan bulat yang ditandatangani -4
. Jadi sebenarnya -4
untuk contoh ini atau Int.MinValue
dalam kasus umum adalah titik tetap kedua negasi aritmatika bilangan bulat - 0
dan Int.MinValue
dipetakan ke mereka sendiri. Jadi siklusnya sebenarnya sebagai berikut.
+3 => -4 => -3 => -4 => -3
Ini adalah siklus dengan panjang dua dan juga +3
memasuki siklus melalui -4
. Karena -4
itu dipetakan dengan benar ke dirinya sendiri setelah dua aplikasi fungsi, +3
dipetakan dengan benar ke -3
setelah dua aplikasi fungsi, tetapi -3
dipetakan secara keliru ke dirinya sendiri setelah dua aplikasi fungsi.
Jadi kami membangun fungsi yang bekerja untuk semua bilangan bulat kecuali satu. Bisakah kita berbuat lebih baik? Tidak, kita tidak bisa. Mengapa? Kita harus membuat siklus dengan panjang empat dan mampu mencakup seluruh rentang integer hingga empat nilai. Nilai yang tersisa adalah dua titik tetap 0
dan Int.MinValue
yang harus dipetakan untuk diri mereka sendiri dan dua bilangan bulat sewenang-wenang x
dan -x
yang harus dipetakan satu sama lain oleh dua aplikasi fungsi.
Untuk memetakan x
ke -x
dan sebaliknya mereka harus membentuk empat siklus dan mereka harus berada di sudut yang berlawanan dari siklus itu. Karena itu 0
dan Int.MinValue
harus berada di sudut yang berlawanan juga. Ini akan memetakan dengan benar x
dan -x
tetapi menukar dua titik tetap 0
dan Int.MinValue
setelah dua aplikasi fungsi dan meninggalkan kita dengan dua input yang gagal. Jadi tidak mungkin untuk membangun fungsi yang bekerja untuk semua nilai, tetapi kami memiliki satu yang berfungsi untuk semua nilai kecuali satu dan ini adalah yang terbaik yang bisa kami capai.