Math 面试问题:f(f(x))==1/x

Math 面试问题:f(f(x))==1/x,math,Math,设计函数f,以便: f(f(x))==1/x 其中x是32位浮点 或者呢 给定一个函数f,求一个函数g 以致 f(x)=g(g(x)) 另见 好吧,这里是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

设计函数f,以便:

f(f(x))==1/x

其中x是32位浮点

或者呢

给定一个函数f,求一个函数g 以致

f(x)=g(g(x))


另见


好吧,这里是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,以便:

  • D=A∪ B、 (分区为总分区)
  • ∅ = A.∩ B(分区是不相交的)
  • σ(a)∈ B、 f(a)∈ A.∀ A.∈ A,
  • σ(b)∈ A、 f(b)∈ B∀ B∈ B,
  • σ有一个逆σ-1 s.t.σ(σ-1(d))=σ-1(σ(d))=d∀ D∈ D
  • σ(f(d))=f(σ(d))∀ D∈ D
  • 然后,您可以这样定义g:

    • g(a)=σ(f(a))∀ A.∈ A
    • g(b)=σ-1(b)∀ B∈ B
    这是b/c模式

    • ∀ A.∈ A、 g(g(A))=g(σ(f(A)),乘以(3),f(A)∈ A soσ(f(A))∈ 所以g(σ(f(a))=σ-1(σ(f(a)))=f(a)
    • ∀ B∈ B、 g(g(B))=g(σ-1(B)),乘以(4),σ-1(B)∈ 因此g(σ-1(b))=σ(f)(σ-1(b))=f(σ(σ-1(b)))=f(b)
    你可以从Miles的回答中看到,如果我们忽略0,那么运算σ(x)=-x对f(x)=1/x有效。你可以检查1-6(对于D=非零实数),其中A为正数,B为负数。使用双精度标准,有A
    +0
    、A
    -0
    、A
    +inf
    、A
    -inf
    ,这些可用于计算域总数(适用于所有双精度数字,而不仅仅是非零)


    同样的方法也可以应用于f(x)=-1问题——这里接受的解决方案使用σ(x)=(x-1)将空间按余数mod 2进行划分,专门处理零情况。

    我喜欢前面线程中的javascript/lambda建议:

    function f(x)
    {
       if (typeof x == "function")
           return x();
       else
           return function () {return 1/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位数据类型32位。

    对于第一部分:这个比f(f(x))=-x更简单,IMO:

    float f(float x)
    {
        return x >= 0 ? -1.0/x : -x;
    }
    
    第二部分是一个有趣的问题,也是对这个问题的一个明显概括。有两种基本方法:

    • 一种数值方法,如x≠ f(x)≠ f(f(x)),我认为这更符合原始问题的精神,但我认为在一般情况下是不可能的
    • 一种涉及g(g(x))只调用f一次的方法

      • 其他解决方案暗示需要额外的状态。以下是一个更为数学化的理由:

        设f(x)=1/(x^i)=x^-i

        (式中,^表示指数,i是假想常数sqrt(-1))

        f(f(x))=(x^-i^-i)=x^(-i*-i)=x^(-1)=1/x

        因此,对于复数存在一个解决方案。我不知道是否有严格遵循实数的通用解决方案。

        基于,一个通用版本的解决方案(作为Perl单行程序):

        应该始终翻转变量的符号(也称为state)两次,并且应该始终只调用
        f()
        一次。对于那些不适合Perl隐式返回的语言,只需在
        {
        之前弹出一个
        return
        ,就可以了

        只要
        f()
        不改变变量的符号,此解决方案就可以工作。在这种情况下,它会返回原始结果(对于负数)或
        f(f())
        (对于正数)的结果。另一种方法可以像上一个问题的答案一样将变量的状态存储为偶数/奇数,但如果
        f,则会中断()
        更改(或可以更改)变量的值。如前所述,更好的答案是lambda解决方案。下面是一个类似但不同的Perl解决方案(使用引用,但概念相同):

        注意:这是经过测试的,不起作用。它总是返回对标量的引用(并且总是同一个引用)。我尝试了一些方法,但这段代码显示了总体思路,尽管我的实现是错误的,方法甚至可能有缺陷,但这是朝着正确方向迈出的一步。通过一些技巧,您甚至可以使用字符串:

        use String::Util qw(looks_like_number);
        
        sub g {
          return "s" . f($_[0]) if looks_like_number $_[0];
          return substr $_[0], 1;
        }
        

        还有另一种方法可以解决这个问题,它使用分数线性变换的概念。这些函数发送x->(ax+b)/(cx+d),其中a,b,c,d是实数

        例如,您可以使用一些代数证明,如果f由f(x)=(ax+1)(-x+d)定义,其中a^2=d^2=1和a+d0,那么对于所有实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)

        这对于x=1或x=0不成立,除非我们允许定义一个“无限”的值满足1 /INF=0, 1/0=INF.< /P> < P>一个<代码> G(g(x))=f(x)< /> >:< /p>的C++解决方案。 这是一个稍微短一点的版本(我更喜欢这个:-)

        如果
        f(x)=g(g(x))
        ,那么
        g
        被称为
        f
        。我认为,即使你允许x是复杂的(你可能想去mathoverflow讨论:),通常也没有封闭形式。

        试试这个

        MessageBox.Show( "x = " + x );
        MessageBox.Show( "value of x + x is " + ( x + x ) );
        MessageBox.Show( "x =" );
        MessageBox.Show( ( x + y ) + " = " + ( y + x ) );
        

        我感觉到大量的问题即将到来……是面试周?还是有人在审查面试问题?“灵感”?这就像是同一个问题!他不是得到面试问题的人。他在这里复制面试问题:面试官的问题:“这到底是如何证明你作为一名专业开发人员的技能的呢?”事实上,这很狡猾(以单线程的方式:-)。是的,但如果我做x=g(3.0),y=g(4.0),z=g(x),a=g(y),它仍然会下降=>z=3.0,a=4.0。我需要一个更好的多值数据结构。我从没想过我第一次看到一阶逻辑会出现在社区网站上
        float f(float x)
        {
            return (x+1)/(-x+1);
        }
        
        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();
        }
        
        MessageBox.Show( "x = " + x );
        MessageBox.Show( "value of x + x is " + ( x + x ) );
        MessageBox.Show( "x =" );
        MessageBox.Show( ( x + y ) + " = " + ( y + x ) );