Це справедливо для всіх від’ємних чисел.
f (n) = abs (n)
Оскільки є ще одне від’ємне число, ніж є додатне число для цілих чисел, що доповнюють двійки, f(n) = abs(n)справедливо для ще одного випадку, ніж f(n) = n > 0 ? -n : nрішення, яке є тим самим, що і рішення f(n) = -abs(n). Зробив вас одним ...: D
ОНОВЛЕННЯ
Ні, це не дійсно для однієї справи більше, оскільки я щойно визнав коментарем лаб ... abs(Int.Min)просто переповниться ...
Я теж думав про використання інформації про мод 2, але зробив висновок, що це не працює ... рано. Якщо зробити все правильно, воно буде працювати для всіх чисел, за винятком того, Int.Minщо це переповниться.
ОНОВЛЕННЯ
Я деякий час грав з ним, шукаючи приємного тріску в маніпуляції, але не зміг знайти приємного однолінійного вкладу, в той час як рішення моди 2 вписується в одне.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
У C # це стає наступним:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Для того, щоб отримати його роботу для всіх значень, ви повинні замінити Math.Abs()з (n > 0) ? +n : -nі включають в розрахунок як uncheckedблоку. Тоді ви навіть Int.Minвідображаєте себе як неперевірене заперечення.
ОНОВЛЕННЯ
Натхненний іншою відповіддю, я збираюся пояснити, як функціонує функція та як побудувати таку функцію.
Почнемо з самого початку. Функція fнеодноразово застосовується до заданого значення, nдаючи послідовність значень.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n))))) => ...
Питання вимагає f(f(n)) = -n, це два послідовних додатки fзаперечення аргументу. Ще два додатки f- всього чотири - заперечують аргумент, знову поступаючись n.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Зараз очевидний цикл довжиною чотири. Підставляючи x = f(n)та зазначаючи, що отримане рівняння f(f(f(n))) = f(f(x)) = -xмає місце, виходить таке.
n => x => -n => -x => n => ...
Таким чином, ми отримуємо цикл довжиною чотири з двома числами, а два числа заперечуються. Якщо ви уявляєте цикл як прямокутник, заперечені значення розташовані в протилежних кутах.
Одним із багатьох рішень для побудови такого циклу є наступне, починаючи з n.
n => відмінити і відняти один
-n - 1 = - (n + 1) => додати один
-n => відмінити і додати його
n + 1 => відняти
н
Конкретний приклад такого циклу є +1 => -2 => -1 => +2 => +1. Ми майже готові. Зауваживши, що побудований цикл містить непарне додатне число, його парний наступник, і обидва числа заперечують, ми можемо легко розділити цілі числа на безліч таких циклів ( 2^32кратне чотирма) і знайшли функцію, яка задовольняє умовам.
Але у нас проблема з нулем. Цикл повинен містити, 0 => x => 0оскільки нуль заперечується самому собі. І тому, що цикл констатує вже 0 => xвипливає 0 => x => 0 => x. Це лише цикл довжиною два і xперетворюється на себе після двох застосувань, а не в -x. На щастя, є один випадок, який вирішує проблему. Якщо Xдорівнює нулю, ми отримуємо цикл довжини один, що містить лише нуль, і ми вирішили цю задачу, зробивши висновок, що нуль є фіксованою точкою f.
Зробили? Майже. У нас є 2^32числа, нуль - це фіксована точка, що залишає 2^32 - 1числа, і ми повинні розділити це число на цикли з чотирьох чисел. Погано, що 2^32 - 1не кратне чотирма - залишиться три числа не в жодному циклі довжиною чотири.
Поясню решту розчину з використанням меншого набору 3 - бітових підписали itegers в межах від -4до +3. Ми робимо з нулем. У нас є один повний цикл +1 => -2 => -1 => +2 => +1. Тепер побудуємо цикл, починаючи з +3.
+3 => -4 => -3 => +4 => +3
Проблема, яка виникає, полягає в тому, що +4це не представлене як 3-бітове ціле число. Ми отримали б +4заперечуючи , -3щоб +3- то , що до сих пір діє 3 розрядне ціле число - але додавання одного до +3(двійковий 011) дає 100бінарної. Інтерпретується як непідписане ціле число, +4але ми маємо трактувати це як підписане ціле число -4. Тож насправді -4для цього прикладу або Int.MinValueв загальному випадку є другою фіксованою точкою цілочисельне арифметичне заперечення - 0 і Int.MinValueвідображаються на їхвелике. Тож цикл насправді такий.
+3 => -4 => -3 => -4 => -3
Це цикл довжиною два і додатково +3входить у цикл через -4. Внаслідок -4цього правильно відображається на собі після двох функціональних додатків, +3правильно відображається -3після двох функціональних додатків, але -3помилково відображається до себе після двох функціональних додатків.
Тому ми побудували функцію, яка працює для всіх цілих чисел, окрім однієї. Чи можемо ми зробити краще? Ні, ми не можемо. Чому? Ми повинні побудувати цикли довжиною чотири і здатні охопити весь цілий діапазон до чотирьох значень. Решта значення є дві нерухомими точками , 0і Int.MinValueякі повинні бути відображені на себе і два довільних цілі числа xі -xякі повинні бути відображені один з одним з допомогою двох додатків функції.
Щоб відобразити xна -xі навпаки , вони повинні утворювати чотири цикли , і вони повинні бути розташовані на протилежних кутках цього циклу. Як наслідок, 0і Int.MinValueвони повинні бути в протилежних кутах. Це буде правильно карту xі -xале поміняти місцями дві фіксовані точки 0і Int.MinValueпісля двох застосувань функції і залишити нас з двох провальних входів. Тому неможливо побудувати функцію, яка працює для всіх значень, але у нас є одна, яка працює для всіх значень, крім однієї, і це найкраще, що ми можемо досягти.