Это верно для всех отрицательных чисел.
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 - 1 = - (n + 1) => добавить один
-n => отменить и добавить один
n + 1 => вычесть один
N
Конкретный пример такого цикла есть +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-битных подписанных итераторов в диапазоне от -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после двух применений функции и оставить нас с двух провальных входов. Таким образом, невозможно создать функцию, которая работает для всех значений, но у нас есть такая, которая работает для всех значений, кроме одного, и это лучшее, чего мы можем достичь.