Math 设计函数f(f(n))=-n
我在上次面试中遇到的一个问题: 设计功能Math 设计函数f(f(n))=-n,math,integer,Math,Integer,我在上次面试中遇到的一个问题: 设计功能f,以便: f(f(n)) == -n 其中n是32位有符号整数;你不能使用复数算术 如果你不能为整个数字范围设计这样一个函数,那么就尽可能为最大范围设计它 有什么想法吗?这适用于所有负数 f(n) = abs(n) 在C#中,这变成以下内容: public static Int32 f(Int32 n) { return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n); } 要使其适用于所有值,必须将
f
,以便:
f(f(n)) == -n
其中n
是32位有符号整数;你不能使用复数算术
如果你不能为整个数字范围设计这样一个函数,那么就尽可能为最大范围设计它
有什么想法吗?这适用于所有负数 f(n) = abs(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
并将计算包含在未选中的块中。然后,您甚至可以像未检查的否定一样将Int.Min
映射到自身
更新
受另一个答案的启发,我将解释函数是如何工作的,以及如何构造这样一个函数
让我们从头开始。函数f
重复应用于给定值n
,产生一系列值
n => f(n) => f(f(n)) => f(f(f(n))) => f(f(f(f(n)))) => ...
现在有一个明显的周期长度为4。替换x=f(n)
并注意到获得的方程f(f(f(n))=f(f(x))=-x成立,得到以下结果
n => x => -n => -x => n => ...
出现的问题是+4
不能表示为3位整数。我们可以通过将-3
与+3
求反来获得+4
——这仍然是一个有效的3位整数——但随后将一个与+3
(二进制011
)相加,得到100
二进制。解释为无符号整数它是+4
,但我们必须解释为有符号整数-4
。因此实际上,在这个例子中,-4
或者在一般情况下,Int.MinValue
是整数算术求反的第二个固定点-0
和Int.MinValue
被映射到它们自己。所以这个循环实际上是这样的
+3 => -4 => -3 => -4 => -3
+3 => -4 => -3 => -4 => -3
这是一个长度为2的循环,另外,+3
通过-4
进入循环。因此,在两次功能应用后,-4
正确映射到自身,+3
在两次功能应用后正确映射到-3
,但在两次功能应用后,-3
错误映射到自身
所以我们构造了一个函数,它适用于除一个整数以外的所有整数。我们能做得更好吗?不,我们不能。为什么?我们必须构造长度为4的循环,并且能够覆盖多达4个值的整个整数范围。其余值是必须映射到自身的两个固定点0
和Int.MinValue
,以及必须通过两个函数应用程序相互映射的两个任意整数x
和-x
要将x
映射到-x
,反之亦然,它们必须形成一个四个循环,并且必须位于该循环的相对角。因此,0
和Int.MinValue
也必须位于相反的角落。这将正确映射x
和-x
,但在两次函数应用后交换两个固定点0
和Int.MinValue
,并留下两个失败的输入。因此,不可能构造一个适用于所有值的函数,但我们有一个适用于除一个值以外的所有值的函数,这是我们所能实现的最佳功能。根据您的平台,某些语言允许您在函数中保留状态。例如,VB.Net:
Function f(ByVal n As Integer) As Integer
Static flag As Integer = -1
flag *= -1
Return n * flag
End Function
iRC+C++也允许这样做。但我怀疑他们正在寻找一个不同的解决方案
另一个想法是,由于他们没有定义第一次调用函数的结果,您可以使用奇数/均匀度来控制是否反转符号:
int f(int n)
{
int sign = n>=0?1:-1;
if (abs(n)%2 == 0)
return ((abs(n)+1)*sign * -1;
else
return (abs(n)-1)*sign;
}
所有偶数的大小加一,所有奇数的大小减一。两次调用的结果大小相同,但一次调用的结果是偶数,我们交换符号。在某些情况下,这将不起作用(-1,max或min int),但它比目前为止建议的任何其他方法都好得多。我可以想象,使用31位作为假想(I)位将是一种支持总范围一半的方法。适用于n=[0..2^31-1]
int f(int n) {
if (n & (1 << 31)) // highest bit set?
return -(n & ~(1 << 31)); // return negative of original n
else
return n | (1 << 31); // return n with highest bit set
}
intf(intn){
如果(n&(1那么:
f(n) = sign(n) - (-1)n * n
Python自动将整数提升到任意长度。在其他语言中,最大的正整数将溢出,因此它将适用于除该整数之外的所有整数
要使其适用于实数,您需要将n in(-1)n替换为{ceiling(n)if n>0;floor(n)if n,但问题并没有说明函数f
的输入类型和返回值必须是什么(至少不是您表示的方式)
…只是当n是32位整数时,f(f(n))=-n
那么,像这样的东西怎么样
Int64 f(Int64 n)
{
return(n > Int32.MaxValue ?
-(n - 4L * Int32.MaxValue):
n + 4L * Int32.MaxValue);
}
如果n是32位整数,则语句f(f(n))==-n
将为真
显然,这种方法可以扩展到更广泛的数字范围…您没有说他们希望使用哪种语言…这是一个静态解决方案(Haskell)。它基本上会弄乱两个最重要的位:
f::Int->Int
f x |(testBit x 30/=testBit x 31)=对$x 30位求反
|否则=位x30
在动态语言(Python)中要容易得多。只需检查参数是否为数字X并返回返回-X的lambda:
def(x):
如果isinstance(x,int):
返回值(λ:-x)
其他:
返回x()
对于javascript(或其他动态类型语言),您可以让函数接受int或object并返回另一个
function f(n) {
if (n.passed) {
return -n.val;
} else {
return {val:n, passed:1};
}
}
给予
js> f(f(10))
-10
js> f(f(-10))
10
或者,您可以在强类型语言中使用重载,尽管这可能会违反规则
int f(long n) {
return n;
}
long f(int n) {
return -n;
}
对于所有32位值(注意-0是-21474836
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)
Int64 f(Int64 n)
{
return(n > Int32.MaxValue ?
-(n - 4L * Int32.MaxValue):
n + 4L * Int32.MaxValue);
}
function f(n) {
if (n.passed) {
return -n.val;
} else {
return {val:n, passed:1};
}
}
js> f(f(10))
-10
js> f(f(-10))
10
int f(long n) {
return n;
}
long f(int n) {
return -n;
}
int rotate(int x)
{
static const int split = INT_MAX / 2 + 1;
static const int negativeSplit = INT_MIN / 2 + 1;
if (x == INT_MAX)
return INT_MIN;
if (x == INT_MIN)
return x + 1;
if (x >= split)
return x + 1 - INT_MIN;
if (x >= 0)
return INT_MAX - x;
if (x >= negativeSplit)
return INT_MIN - x + 1;
return split -(negativeSplit - x);
}
0 => 7 => -8 => -7 => 0
1 => 6 => -1 => -6 => 1
2 => 5 => -2 => -5 => 2
3 => 4 => -3 => -4 => 3
Func<int, int> f = n =>
n < 0
? (n & (1 << 30)) == (1 << 30) ? (n ^ (1 << 30)) : - (n | (1 << 30))
: (n & (1 << 30)) == (1 << 30) ? -(n ^ (1 << 30)) : (n | (1 << 30));
Console.WriteLine(f(f(Int32.MinValue + 1))); // -2147483648 + 1
for (int i = -3; i <= 3 ; i++)
Console.WriteLine(f(f(i)));
Console.WriteLine(f(f(Int32.MaxValue))); // 2147483647
2147483647
3
2
1
0
-1
-2
-3
-2147483647
boolean inner = true;
int f(int input) {
if(inner) {
inner = false;
return input;
} else {
inner = true;
return -input;
}
}
int f(int n):
if n == 0 or n == MIN_INT or n == MAX_INT: return n
return ((Math.abs(n) mod 2) * 2 - 1) * n + Math.sign(n)
template <class T>
struct f_result
{
T value;
};
template <class T>
f_result <T> f (T n)
{
f_result <T> result = {n};
return result;
}
template <class T>
T f (f_result <T> n)
{
return -n.value;
}
void main (void)
{
int n = 45;
cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
float p = 3.14f;
cout << "f(f(" << p << ")) = " << f(f(p)) << endl;
}
bool done = false
f(int n)
{
int out = n;
if(!done)
{
out = n * -1;
done = true;
}
return out;
}
return x ^ ((x%2) ? 1 : -INT_MAX);
int32 f(int32 x) {
static bool idempotent = false;
if (!idempotent) {
idempotent = true;
return -x;
} else {
return x;
}
}
int32 f (int32 x) {
static int32 answer = -x;
return answer;
}
1. take n, which is a signed 32-bit integer.
2. swap the first bit and the second bit.
3. flip the first bit.
4. return the result.
int32_t f(int32_t x)
{
return (((x & 0xFFFFU) << 16) | ((x & 0xFFFF0000U) >> 16)) ^ 0xFFFFU;
}
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)
00.... => 01.... => 10.....
01.... => 10.... => 11.....
10.... => 11.... => 00.....
11.... => 00.... => 01.....
; input %edi
; output %eax
; clobbered regs: %ecx, %edx
f:
testl %edi, %edi
je .zero
movl %edi, %eax
movl $1, %ecx
movl %edi, %edx
andl $1, %eax
addl %eax, %eax
subl %eax, %ecx
xorl %eax, %eax
testl %edi, %edi
setg %al
shrl $31, %edx
subl %edx, %eax
imull %ecx, %eax
subl %eax, %edi
movl %edi, %eax
imull %ecx, %eax
.zero:
xorl %eax, %eax
ret
sub f {
my $n = shift;
return ref($n) ? -$$n : \$n;
}
print $_, ' ', f(f($_)), "\n" for -2, 0, 1, 1.1, -3.3, 'foo' '-bar';
-2 2
0 0
1 -1
1.1 -1.1
-3.3 3.3
foo -foo
-bar +bar
def f(x):
if type(x) == list:
return -x[0]
return [x]
f(2) => [2]
f(f(2)) => -2
def mods(x, n):
y = x % n
if y > n/2: y-= n
return y
def f(x):
return mods(x*1849436465, 2**32-3)
function f(n) {
try {
return n();
}
catch(e) {
return function() { return -n; };
}
}
public static int f(int x)
{
if (x == 0) return 0;
if ((x % 2) != 0)
return x * -1 + (-1 *x) / (Math.Abs(x));
else
return x - x / (Math.Abs(x));
}