Це справедливо для всіх від’ємних чисел.
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
після двох застосувань функції і залишити нас з двох провальних входів. Тому неможливо побудувати функцію, яка працює для всіх значень, але у нас є одна, яка працює для всіх значень, крім однієї, і це найкраще, що ми можемо досягти.