设计一个函数f:
f(f(x))== 1 / x
其中x是32位浮点数
或者怎么样
给定函数f,找到函数g 这样
f(x)== g(g(x))
答案 0 :(得分:23)
对于第一部分:这一部分比f(f(x))= -x更为平凡,IMO:
float f(float x)
{
return x >= 0 ? -1.0/x : -x;
}
第二部分是一个有趣的问题,这个问题的基础是the original question的明显概括。有两种基本方法:
答案 1 :(得分:12)
嗯,这是C快攻:
extern double f(double x);
double g(double x)
{
static int parity = 0;
parity ^= 1;
return (parity ? x : f(x));
}
但是,如果你这样做会失败:
a = g(4.0); // => a = 4.0, parity = 1
b = g(2.0); // => b = f(2.0), parity = 0
c = g(a); // => c = 4.0, parity = 1
d = g(b); // => d = f(f(2.0)), parity = 0
一般来说,如果f是双射f:D→D,你需要的是一个函数σ,它将域D划分为A和B,这样:
然后,你可以这样定义g:
这适用于b / c
你可以从Miles回答中看到,如果我们忽略0,那么操作σ(x)= -x适用于f(x)= 1 / x。您可以检查1-6(对于D =非零实数),A为正数,B为负数。使用双精度标准,有一个+0
,一个-0
,一个+inf
和一个-inf
,这些可用于使域总数(适用于所有双精度数,而不仅仅是非零数。)
同样的方法可以应用于f(x)= -1问题 - 使用σ(x)=(x - 1)将剩余的mod 2分隔空间的接受解决方案,特别处理零情况
答案 2 :(得分:11)
我喜欢早期帖子中的javascript / lambda建议:
function f(x)
{
if (typeof x == "function")
return x();
else
return function () {return 1/x;}
}
答案 3 :(得分:2)
其他解决方案暗示需要额外的状态。以下是对此的更多数学证明:
let f(x) = 1/(x^i)= x^-i
(其中^表示指数,i是虚常数sqrt(-1))
f(f(x)) = (x^-i)^-i) = x^(-i*-i) = x^(-1) = 1/x
因此存在复杂数字的解决方案。我不知道是否有一般性解决方案严格遵守实数。
答案 4 :(得分:1)
同样,它被指定为32位数字。使返回有更多位,使用它们在调用之间传递状态信息。
Const
Flag = $100000000;
Function F(X : 32bit) : 64bit;
Begin
If (64BitInt(X) And Flag) > 0 then
Result := g(32bit(X))
Else
Result := 32BitInt(X) Or Flag;
End;
对于任何函数g和任何32位数据类型32位。
答案 5 :(得分:1)
还有另一种解决方法,它使用分数线性变换的概念。这些是发送x->(ax + b)/(cx + d)的函数,其中a,b,c,d是实数。
例如,您可以使用某些代数证明,如果f由f(x)=(ax + 1)( - x + d)定义,其中a ^ 2 = d ^ 2 = 1且a + d<> 0然后对于所有实数x,f(f(x))= 1 / x。选择a = 1,d = 1,这就解决了C ++中的问题:
float f(float x)
{
return (x+1)/(-x+1);
}
证明是f(f(x))= f((x + 1)/( - x + 1))=((x + 1)/( - x + 1)+1)/( - ( X + 1)/( - X + 1)+1) 抵消(1-x)时=(2 /(1-x))/(2x /(1-x))= 1 / x。
除非我们允许定义满足1 / inf = 0,1 / 0 = inf的“无限”值,否则这对x = 1或x = 0不起作用。
答案 6 :(得分:1)
g(g(x)) == f(x)
的C ++解决方案:
struct X{
double val;
};
X g(double x){
X ret = {x};
return ret;
}
double g(X x){
return f(x.val);
}
这是一个更短的版本(我更喜欢这个:-))
struct X{
X(double){}
bool operator==(double) const{
return true
}
};
X g(X x){
return X();
}
答案 7 :(得分:1)
如果f(x) == g(g(x))
,则g
被称为f
的{{3}}。即使你允许 x 复杂,我也不认为有一般的封闭形式(你可能想去mathoverflow讨论:))。
答案 8 :(得分:0)
基于this answer,广义版本的解决方案(作为Perl单线程):
sub g { $_[0] > 0 ? -f($_[0]) : -$_[0] }
应始终翻转变量的符号(a.k.a.状态)两次,并且应始终只调用f()
一次。对于那些不足以获得Perl隐含回报的语言,只需在return
之前点击{
,就可以了。
只要f()
不更改变量的符号,此解决方案就可以正常工作。在这种情况下,它返回原始结果(对于负数)或f(f())
的结果(对于正数)。替代方法可以将变量的状态存储为偶数/奇数,就像前一个问题的答案一样,但如果f()
改变(或可以改变)变量的值,它就会中断。如前所述,更好的答案是lambda解决方案。这是Perl中类似但不同的解决方案(使用引用,但概念相同):
sub g {
if(ref $_[0]) {
return ${$_[0]};
} else {
local $var = f($_[0]);
return \$var;
}
}
注意:这已经过测试,并且不有效。它总是返回对标量的引用(并且它始终是相同的引用)。我已经尝试了一些东西,但是这段代码显示了一般的想法,虽然我的实现是错误的,并且方法甚至可能有缺陷,但它是朝着正确方向迈出的一步。有了一些技巧,你甚至可以使用一个字符串:
use String::Util qw(looks_like_number);
sub g {
return "s" . f($_[0]) if looks_like_number $_[0];
return substr $_[0], 1;
}
答案 9 :(得分:-1)
试试这个
MessageBox.Show( "x = " + x );
MessageBox.Show( "value of x + x is " + ( x + x ) );
MessageBox.Show( "x =" );
MessageBox.Show( ( x + y ) + " = " + ( y + x ) );