对于第一部分:在我看来,这比f(f(x)) = -x要更平凡:
float f(float x)
{
return x >= 0 ? -1.0/x : -x;
}
第二部分是一个有趣的问题,也是原始问题的明显推广。有两种基本方法:
x
的+0
和-0
,您可以使用表达式x > 0.0 || (x == 0.0 && 1.0 / x > 0.0)
。后面的表达式将把+0
映射到+Inf
,将-0
映射到-Inf
。 - Roland Illig好的,这里是 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,使得:
+0
,一个-0
,一个+inf
和一个-inf
,这些可以用于使定义域总体(应用于所有双精度数字,而不仅仅是非零数字)。我喜欢之前帖子中提到的 JavaScript/lambda 建议:
function f(x)
{
if (typeof x == "function")
return x();
else
return function () {return 1/x;}
}
一个关于 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();
}
再次强调,它被指定为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 位数据类型 32bit。
有另一种解决方法,它使用分数线性变换的概念。这些是将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) = (2/(1-x))/(2x/(1-x))=1/x,消去(1-x)。
除非我们允许定义一个“无限”的值满足1/inf = 0,1/0 = inf,否则此公式对于x=1或x=0不起作用。
基于这个答案,一个通用版本的解决方案(作为Perl一行代码):
sub g { $_[0] > 0 ? -f($_[0]) : -$_[0] }
应该始终两次翻转变量的符号(也称为状态),并且应该始终仅调用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;
}
试一下这个
MessageBox.Show( "x = " + x );
MessageBox.Show( "value of x + x is " + ( x + x ) );
MessageBox.Show( "x =" );
MessageBox.Show( ( x + y ) + " = " + ( y + x ) );