我在上次面试中遇到的一个问题是:

设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。

有什么想法吗?


当前回答

由于C++中的重载:

double f(int var)
{
 return double(var);
} 

int f(double var)
{
 return -int(var);
}

int main(){
int n(42);
std::cout<<f(f(n));
}

其他回答

number f( number n)
{
  static count(0);
  if(count > 0) return -n;
  return n;
}

f(n) = n

f(f(n)) = f(n) = -n

类似于python中的函数重载解决方案:

def f(number):
 if type(number) != type([]):
  return [].append(number)
 else:
  return -1*number[0]

备选方案:静态数据成员

该问题表示“32位有符号整数”,但没有指定它们是2个补码还是1个补码。

如果使用1补码,则所有2^32值都出现在长度为4的循环中-不需要零的特殊情况,也不需要条件。

在C中:

int32_t f(int32_t x)
{
  return (((x & 0xFFFFU) << 16) | ((x & 0xFFFF0000U) >> 16)) ^ 0xFFFFU;
}

这项工作由

交换高位和低位16位块反转其中一个块

两次传递后,我们得到原始值的位逆。在一中补语表示等同于否定。

示例:

Pass |        x
-----+-------------------
   0 | 00000001      (+1)
   1 | 0001FFFF (+131071)
   2 | FFFFFFFE      (-1)
   3 | FFFE0000 (-131071)
   4 | 00000001      (+1)

Pass |        x
-----+-------------------
   0 | 00000000      (+0)
   1 | 0000FFFF  (+65535)
   2 | FFFFFFFF      (-0)
   3 | FFFF0000  (-65535)
   4 | 00000000      (+0)

怎么样:

f(n) = sign(n) - (-1)ⁿ * n

在Python中:

def f(n): 
    if n == 0: return 0
    if n >= 0:
        if n % 2 == 1: 
            return n + 1
        else: 
            return -1 * (n - 1)
    else:
        if n % 2 == 1:
            return n - 1
        else:
            return -1 * (n + 1)

Python自动将整数提升为任意长度的longs。在其他语言中,最大的正整数将溢出,因此它将适用于除该整数之外的所有整数。


为了使其适用于实数,您需要替换(-1)中的nⁿ 如果n>0,则为{上限(n);如果n<0},则为下限(n)。

在C#中(适用于任何双精度,溢出情况除外):

static double F(double n)
{
    if (n == 0) return 0;
    
    if (n < 0)
        return ((long)Math.Ceiling(n) % 2 == 0) ? (n + 1) : (-1 * (n - 1));
    else
        return ((long)Math.Floor(n) % 2 == 0) ? (n - 1) : (-1 * (n + 1));
}

或者,您可以滥用预处理器:

#define f(n) (f##n)
#define ff(n) -n

int main()
{
  int n = -42;
  cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
}