Designing function f(f(n)) == -n

前端 未结 30 2814
清酒与你
清酒与你 2020-12-02 03:32

A question I got on my last interview:

Design a function f, such that:

f(f(n)) == -n

Where n<

相关标签:
30条回答
  • 2020-12-02 03:42

    A C++ version, probably bending the rules somewhat but works for all numeric types (floats, ints, doubles) and even class types that overload the unary minus:

    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;
    }
    
    0 讨论(0)
  • 2020-12-02 03:43

    I could imagine using the 31st bit as an imaginary (i) bit would be an approach that would support half the total range.

    0 讨论(0)
  • 2020-12-02 03:45

    Using complex numbers, you can effectively divide the task of negating a number into two steps:

    • multiply n by i, and you get n*i, which is n rotated 90° counter-clockwise
    • multiply again by i, and you get -n

    The great thing is that you don't need any special handling code. Just multiplying by i does the job.

    But you're not allowed to use complex numbers. So you have to somehow create your own imaginary axis, using part of your data range. Since you need exactly as much imaginary (intermediate) values as initial values, you are left with only half the data range.

    I tried to visualize this on the following figure, assuming signed 8-bit data. You would have to scale this for 32-bit integers. The allowed range for initial n is -64 to +63. Here's what the function does for positive n:

    • If n is in 0..63 (initial range), the function call adds 64, mapping n to the range 64..127 (intermediate range)
    • If n is in 64..127 (intermediate range), the function subtracts n from 64, mapping n to the range 0..-63

    For negative n, the function uses the intermediate range -65..-128.

    alt text

    0 讨论(0)
  • 2020-12-02 03:45

    :D

    boolean inner = true;
    
    int f(int input) {
       if(inner) {
          inner = false;
          return input;
       } else {
          inner = true;
          return -input;
       }
    }
    
    0 讨论(0)
  • 2020-12-02 03:46

    The problem states "32-bit signed integers" but doesn't specify whether they are twos-complement or ones-complement.

    If you use ones-complement then all 2^32 values occur in cycles of length four - you don't need a special case for zero, and you also don't need conditionals.

    In C:

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

    This works by

    1. Exchanging the high and low 16-bit blocks
    2. Inverting one of the blocks

    After two passes we have the bitwise inverse of the original value. Which in ones-complement representation is equivalent to negation.

    Examples:

    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)
    
    0 讨论(0)
  • 2020-12-02 03:47

    I'm not actually trying to give a solution to the problem itself, but do have a couple of comments, as the question states this problem was posed was part of a (job?) interview:

    • I would first ask "Why would such a function be needed? What is the bigger problem this is part of?" instead of trying to solve the actual posed problem on the spot. This shows how I think and how I tackle problems like this. Who know? That might even be the actual reason the question is asked in an interview in the first place. If the answer is "Never you mind, assume it's needed, and show me how you would design this function." I would then continue to do so.
    • Then, I would write the C# test case code I would use (the obvious: loop from int.MinValue to int.MaxValue, and for each n in that range call f(f(n)) and checking the result is -n), telling I would then use Test Driven Development to get to such a function.
    • Only if the interviewer continues asking for me to solve the posed problem would I actually start to try and scribble pseudocode during the interview itself to try and get to some sort of an answer. However, I don't really think I would be jumping to take the job if the interviewer would be any indication of what the company is like...

    Oh, this answer assumes the interview was for a C# programming related position. Would of course be a silly answer if the interview was for a math related position. ;-)

    0 讨论(0)
提交回复
热议问题