답변:
어때요?
f (n) = 부호 (n)-(-1) n * n
파이썬에서 :
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)
파이썬은 정수를 임의의 길이로 자동 승격시킵니다. 다른 언어에서는 가장 큰 양의 정수가 오버플로되므로 해당 정수를 제외한 모든 정수에서 작동합니다.
그것은 실수 작동하려면 당신은 교체해야 N 에서 (-1) N 과 함께 { ceiling(n) if n>0; floor(n) if n<0 }
.
C #에서 (오버플로 상황을 제외하고 두 배로 작동) :
static double F(double n)
{
if (n == 0) return 0;
if (n < 0)
return ((long)Math.Ceiling(n) % 2 == 0) ? (n + 1) : (-1 * (n - 1));
else
return ((long)Math.Floor(n) % 2 == 0) ? (n - 1) : (-1 * (n + 1));
}
당신은 그들이 어떤 종류의 언어를 기대했는지 말하지 않았다 ... 정적 솔루션 (Haskell)이있다. 기본적으로 가장 중요한 2 비트를 망칩니다.
f :: Int -> Int
f x | (testBit x 30 /= testBit x 31) = negate $ complementBit x 30
| otherwise = complementBit x 30
동적 언어 (Python)에서는 훨씬 쉽습니다. 인수가 숫자 X인지 확인하고 -X를 반환하는 람다를 반환하십시오.
def f(x):
if isinstance(x,int):
return (lambda: -x)
else:
return x()
class C a b | a->b where { f :: a->b }
. instance C Int (()->Int) where { f=const.negate }
; instance C (()->Int) Int where { f=($()) }
.
추가 정보를 사용하지 않는 경우 (32 비트 int 제외) 모든 숫자에 대해 그러한 함수가 존재하지 않는 이유에 대한 증거는 다음과 같습니다.
f (0) = 0이어야합니다. (증거 : f (0) = x라고 가정 한 다음 f (x) = f (f (0)) = -0 = 0이라고 가정하십시오. )) = f (0) = x, 이는 x = 0을 의미합니다.)
또한 임의의 x
및 y
에 대해 가정 f(x) = y
합니다. 우리는 f(y) = -x
그때 원합니다 . 그리고 f(f(y)) = -y => f(-x) = -y
. 요약하면 : 만약 f(x) = y
, 다음 f(-x) = -y
,와 f(y) = -x
,와 f(-y) = x
.
따라서 0을 제외한 모든 정수를 4 개의 세트로 나눌 필요가 있지만 홀수의 정수가 있습니다. 뿐만 아니라 양의 상대가없는 정수를 제거해도 여전히 2 (mod4) 개의 숫자가 있습니다.
남아있는 최대 값 2 개를 제거하면 (abs 값으로) 함수를 얻을 수 있습니다.
int sign(int n)
{
if(n>0)
return 1;
else
return -1;
}
int f(int n)
{
if(n==0) return 0;
switch(abs(n)%2)
{
case 1:
return sign(n)*(abs(n)+1);
case 0:
return -sign(n)*(abs(n)-1);
}
}
물론 다른 옵션은 0을 준수하지 않고 보너스로 제거한 2 개의 숫자를 얻는 것입니다. (그러나 그것은 바보 같은 경우입니다.)
n = -2147483648
(최소 값)를 주의하십시오 . 이 abs(n)
경우에는 불가능 하며 결과는 정의되지 않습니다 (또는 예외).
C ++의 과부하로 인해 :
double f(int var)
{
return double(var);
}
int f(double var)
{
return -int(var);
}
int main(){
int n(42);
std::cout<<f(f(n));
}
또는 전처리기를 남용 할 수 있습니다.
#define f(n) (f##n)
#define ff(n) -n
int main()
{
int n = -42;
cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
}
이것은 모든 음수에 해당됩니다.
f (n) = abs (n)
2의 보수 정수에 대한 양수보다 하나 이상의 음수가 있기 때문에 와 동일한 해보다 f(n) = abs(n)
하나 이상의 경우에 유효합니다 . 하나 하나 당신이 ... : Df(n) = n > 0 ? -n : n
f(n) = -abs(n)
최신 정보
아니요, 방금 litb의 의견으로 인식 한대로 더 이상 유효하지 않습니다 abs(Int.Min)
...
나는 mod 2 정보 사용에 대해서도 생각했지만 초기에는 작동하지 않는다고 결론지었습니다. 올바르게 수행 Int.Min
하면 오버플로되기 때문에 모든 숫자에 대해 작동합니다 .
최신 정보
나는 잠시 동안 그것을 가지고 놀면서 멋진 비트 조작 트릭을 찾았지만 멋진 2 라이너를 찾을 수 없지만 mod 2 솔루션은 1에 맞습니다.
f (n) = 2n (abs (n) % 2)-n + sgn (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
와의 계산에 포함 unchecked
블록. 그런 다음 Int.Min
확인되지 않은 부정과 마찬가지로 자체 매핑됩니다.
최신 정보
다른 답변에서 영감을 얻어 함수가 작동하는 방식과 그러한 함수를 구성하는 방법에 대해 설명하겠습니다.
처음부터 시작할 수 있습니다. 함수 f
는 주어진 값에 반복적으로 적용되어 n
일련의 값을 산출합니다.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n)))) => ...
의문 f(f(n)) = -n
을 f
무효화하는 두 가지 연속적인 적용이다 . f
총 4 건의 2 건의 추가 적용은 논증을 다시 무효화 n
합니다.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
이제 길이 4의 명백한주기가 있습니다. x = f(n)
획득 된 방정식이 f(f(f(n))) = f(f(x)) = -x
보유 하고 있음을 대체 하고 주목 하면 다음과 같은 결과가 나온다.
n => x => -n => -x => n => ...
따라서 우리는 두 개의 숫자를 가진 길이가 4이고 두 개의 숫자는 부정됩니다. 주기를 직사각형으로 가정하면 무시 된 값이 반대편 모서리에 있습니다.
이러한주기를 구성하는 많은 솔루션 중 하나는 n부터 시작하는 다음과 같습니다.
n => 부정하고 빼기 -n-1 =-(n + 1) => 하나 추가 -n => 부정하고 하나 추가 n + 1 => 하나 빼기 엔
구체적인 예는 다음과 같습니다 +1 => -2 => -1 => +2 => +1
. 우리는 거의 끝났습니다. 생성 된 사이클에 홀수 양수가 포함되어 있고 짝수의 후속 숫자도 무시하고 정수를 여러 사이클 ( 2^32
4의 배수) 로 쉽게 분할 할 수 있으며 조건을 만족시키는 함수를 찾았습니다.
그러나 우리는 0에 문제가 있습니다. 0 => x => 0
0은 자체적으로 부정되므로 주기가 포함되어야합니다 . 그리고주기 상태는 이미 0 => x
다음과 같습니다 0 => x => 0 => x
. 이것은 단지 길이가 2의주기 일 뿐이며, x
두 번의 애플리케이션이 아닌 자체로 바뀝니다 -x
. 운좋게도 문제를 해결하는 한 가지 사례가 있습니다. 경우 X
등호 제로 우리는 제로를 포함하는 길이 하나의 사이클을 얻고 제로의 고정 점이라고 우리는 그 문제의 결론을 해결 f
.
끝난? 거의. 우리는 2^32
숫자가 있고, 0은 2^32 - 1
숫자를 남기는 고정 소수점 이며, 그 숫자를 4 개의 숫자로 나누어야합니다. 2^32 - 1
4의 배수가 아닌 나쁜 것 -길이 4의 어떤주기에도 3 개의 숫자가 남아 있습니다.
나는 이르기까지 3 비트 부호 itegers의 작은 세트를 사용하여 솔루션의 나머지 부분 설명 할 것 -4
을을 +3
. 우리는 0으로 끝납니다. 하나의 완전한주기가 +1 => -2 => -1 => +2 => +1
있습니다. 이제부터 시작하는 사이클을 구성하겠습니다 +3
.
+3 => -4 => -3 => +4 => +3
발생하는 문제는 +4
3 비트 정수로 표현할 수 없다는 것입니다. 우리는 얻을 것이다 +4
부정에 의해 -3
에 +3
여전히 유효한 3 비트 정수 무엇인지 - -하지만 하나를 추가 +3
(이진은 011
) 산출 100
진. 부호없는 정수로 해석되지만 부호있는 정수 +4
로 해석해야합니다 -4
. 그래서, 실제로 -4
이 실시 예 또는 Int.MinValue
일반적인 경우는 정수 산술 부정의 제 2 고정 점 인 - 0
및 Int.MinValue
themselve 매핑된다. 따라서주기는 실제로 다음과 같습니다.
+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
두 개의 함수 응용 프로그램을 바꾼 다음 두 개의 실패한 입력으로 남겨 둡니다. 따라서 모든 값에 대해 작동하는 함수를 구성 할 수는 없지만 하나를 제외한 모든 값에 대해 작동하는 함수가 있으며 이것이 달성 할 수있는 최선입니다.
복소수를 사용하면 숫자 무효화 작업을 두 단계로 효과적으로 나눌 수 있습니다.
가장 좋은 점은 특별한 처리 코드가 필요 없다는 것입니다. i를 곱하면 작업이 수행됩니다.
그러나 복잡한 숫자는 사용할 수 없습니다. 따라서 데이터 범위의 일부를 사용하여 자신 만의 가상 축을 만들어야합니다. 초기 값만큼의 가상 (중간) 값이 정확히 필요하므로 데이터 범위의 절반 만 남습니다.
서명 된 8 비트 데이터를 가정하여 다음 그림에서 이것을 시각화하려고했습니다. 이것을 32 비트 정수로 확장해야합니다. 초기 n에 허용되는 범위는 -64 ~ +63입니다. 양의 n에 대해 함수가 수행하는 작업은 다음과 같습니다.
음수 n의 경우이 함수는 중간 범위 -65 ..- 128을 사용합니다.
float
vs 사용 int
). 많은 답변에서 설명하는 '4 요소 링'은 4 개의 상태를 필요로하며, 2 개의 상태를 갖는 2 차원으로 표현 될 수 있습니다. 이 답변 의 문제점 은 추가 처리 공간 (-64..63의 경우 '작동'이지만 -128..127의 공간이 필요함)이 필요하고 서면 수식을 명시 적으로 명시하지 않는다는 것입니다!
int.MaxValue 및 int.MinValue를 제외한 작동
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));
}
0
에 0
과 -2147483648
에 -2147483648
, 부정 연산자에 대한이 두 숫자가 고정되어 있기 때문에 포인트 x => -x
. 나머지 숫자는 위 이미지의 화살표를 따르십시오. SurDin의 대답과 설명에서 알 수있는 바와 같이,이 경우, 두 수있을 것 2147483647
와 -2147483647
와 스왑에 남아 다른 쌍.
문제는 입력 유형 및 함수의 반환 값이 무엇인지에 대해 아무것도 말하지 않는다 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
이 참입니다.
분명히이 접근법은 더 넓은 범위의 숫자에서 작동하도록 확장 될 수 있습니다 ...
자바 스크립트 (또는 다른 동적 유형 언어)의 경우 함수가 int 또는 객체를 수락하고 다른 객체를 반환하도록 할 수 있습니다. 즉
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;
}
플랫폼에 따라 일부 언어를 통해 기능 상태를 유지할 수 있습니다. VB.Net의 예 :
Function f(ByVal n As Integer) As Integer
Static flag As Integer = -1
flag *= -1
Return n * flag
End Function
IIRC, 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을 더하고 모든 홀수의 크기에서 1을 뺍니다. 두 번의 호출 결과는 같은 크기이지만 한 번의 호출로도 부호를 바꿉니다. 이것이 작동하지 않는 경우가 있지만 (-1, max 또는 min int), 지금까지 제안 된 것보다 훨씬 잘 작동합니다.
모든 32 비트 값 (-0은 -2147483648이라는 경고)
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);
}
기본적으로 각 -x => x => -x 루프를 ay => -y => y 루프와 쌍으로 연결해야합니다. 그래서 나는 반대편을 페어링했습니다 split
.
예를 들어 4 비트 정수의 경우 :
0 => 7 => -8 => -7 => 0
1 => 6 => -1 => -6 => 1
2 => 5 => -2 => -5 => 2
3 => 4 => -3 => -4 => 3
C ++ 버전은 규칙을 다소 구부릴 수 있지만 모든 숫자 유형 (floats, ints, doubles) 및 단항 빼기에 과부하가 걸리는 클래스 유형에서도 작동합니다.
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;
}
x86 asm (AT & T 스타일) :
; 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
코드 검사, 가능한 모든 32 비트 정수 전달, -2147483647 (언더 플로우) 오류.
글로벌을 사용하지만 ... 그렇습니까?
bool done = false
f(int n)
{
int out = n;
if(!done)
{
out = n * -1;
done = true;
}
return out;
}
이 Perl 솔루션 은 정수, 부동 소수점 및 문자열에 작동합니다 .
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
n
문자열 인 경우 548을 "First_Time_548"로 만들고 다음에 함수를 실행할 때 ... (prefix == First_Time_ ")"First_Time_ "을"- "로 바꾸십시오.
나는 실제로 문제 자체에 대한 해결책을 제시하려고하지는 않지만이 문제가 제기 된 질문은 (직업?) 면접의 일부라고 언급하면서 몇 가지 의견이 있습니다.
int.MinValue
to to int.MaxValue
, n
해당 범위의 각 호출 f(f(n))
및 결과 확인은 -n
) 테스트 구동 개발을 사용하여 해당 기능을 사용하도록 지시합니다.오,이 답변은 인터뷰가 C # 프로그래밍 관련 위치에 대한 것이라고 가정합니다. 인터뷰가 수학 관련 직책에 대한 것이라면 어리석은 대답 일 것입니다. ;-)
가장 중요한 비트 2 개를 변경하겠습니다.
00.... => 01.... => 10.....
01.... => 10.... => 11.....
10.... => 11.... => 00.....
11.... => 00.... => 01.....
보시다시피, 그것은 단지 추가이며 캐리 비트를 제외합니다.
어떻게 대답 했습니까? 나의 첫 생각은 단지 대칭의 필요성이었다. 4는 내가 시작한 곳으로 돌아갑니다. 처음에는 2 비트 그레이 코드라고 생각했습니다. 그런 다음 표준 바이너리로 충분하다고 생각했습니다.
이 문제를 해결하기 위해 복소수를 사용할 수 없다는 요구 사항이나 주장에서 영감을 얻은 솔루션이 있습니다.
-1에 제곱근을 곱하면 -1에 정수에 대한 제곱근이 없기 때문에 실패하는 것 같습니다. 하지만 수학과 같은 프로그램을 가지고 놀면
(1849436465 2 +1) mod (2 32 -3) = 0입니다.
그리고 이것은 -1의 제곱근을 갖는 것만큼이나 좋습니다. 함수의 결과는 부호있는 정수 여야합니다. 따라서 수정 된 모듈로 연산 mods (x, n)을 사용하여 0에 가장 가까운 x 모듈로 n과 일치하는 정수 y를 반환합니다. 프로그래밍 언어가 suc 인 모듈로 연산은 거의 없지만 쉽게 정의 할 수 있습니다. . 예를 들어 파이썬에서는 다음과 같습니다.
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)
이것은 f(f(x)) = -x
범위의 모든 정수에 해당합니다 . 결과 도이 범위에 있지만 물론 계산에는 64 비트 정수가 필요합니다.[-2
31
-2, 2
31
-2]
f(x)
2 ^ 32-1 범위의 숫자에 대한 C # (Int32.MinValue)를 제외한 모든 int32 숫자
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
기본적으로이 함수는 사용 가능한 범위를 크기 4의 주기로 나누어야하며, n주기의 반대쪽 끝에 -n이 있어야합니다. 그러나 0은 크기가 1 인 사이클의 일부 여야합니다 0->x->0->x != -x
. 그렇지 않으면 . 0은 단독이므로 4 개의 요소가있는 적절한주기가 아닌 범위 내에 3 개의 다른 값 (크기가 4의 배수)이 있어야합니다.
나는 것으로 이러한 추가 이상한 값을 선택 MIN_INT
, MAX_INT
하고 MIN_INT+1
. 또한 올바르게 MIN_INT+1
매핑 MAX_INT
되지만 거기에 붙어 다시 매핑되지 않습니다. 나는 이것이 최선의 타협이라고 생각합니다. 왜냐하면 극단적 인 값의 좋은 속성이 올바르게 작동하지 않기 때문입니다. 또한 모든 BigInts에서 작동한다는 의미 입니다.
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)
아무도 무국적자 여야한다고 말한 사람은 없다.
int32 f(int32 x) {
static bool idempotent = false;
if (!idempotent) {
idempotent = true;
return -x;
} else {
return x;
}
}
부정 행위이지만 많은 예 만큼은 아닙니다. 호출자의 주소가 & f인지 확인하기 위해 스택을 들여다 보는 것이 더 악한 일이지만 더 안전합니다 (스레드 안전하지는 않지만 스레드 안전 버전은 TLS를 사용합니다). 더 악한 :
int32 f (int32 x) {
static int32 answer = -x;
return answer;
}
물론, 이들 중 어느 것도 MIN_INT32의 경우에는 잘 작동하지 않지만 더 넓은 유형을 반환하지 않으면 그렇게 할 수있는 일은 거의 없습니다.
나는 31 비트를 상상의 ( i ) 비트로 사용하여 전체 범위의 절반을 지원하는 접근법을 상상할 수 있습니다.
이 문제는 "32 비트 부호있는 정수"를 나타내지 만 이들이 2의 보수 인지 1의 보수 인지를 지정하지는 않습니다 .
ones-complement를 사용하면 모든 2 ^ 32 값이 길이 4의 주기로 발생합니다. 0의 경우에는 특별한 경우가 필요하지 않으며 조건부도 필요하지 않습니다.
C에서 :
int32_t f(int32_t x)
{
return (((x & 0xFFFFU) << 16) | ((x & 0xFFFF0000U) >> 16)) ^ 0xFFFFU;
}
이것에 의해 작동
두 번의 통과 후에 우리는 원래 값의 비트 역수를가집니다. 1의 보수 표현 중 어느 것이 부정과 동일합니다.
예 :
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)
수학자로서이 흥미로운 문제에 대한 견해를 나누고 싶습니다. 가장 효율적인 솔루션이 있다고 생각합니다.
올바르게 기억한다면 첫 번째 비트를 뒤집어 부호있는 32 비트 정수를 부정하십시오. 예를 들어, n = 1001 1101 1110 1011 1110 0000 1110 1010이면 -n = 0001 1101 1110 1011 1110 0000 1110 1010입니다.
그렇다면 부호있는 32 비트 정수를 취하고 f를 두 번 취하는 것이 첫 번째 비트를 뒤집는 것과 동일한 속성으로 다른 부호있는 32 비트 정수를 반환하는 함수 f를 어떻게 정의합니까?
정수와 같은 산술 개념을 언급하지 않고 질문을 다시 설명하겠습니다.
f를 두 번 취하는 것이 첫 번째 비트를 뒤집는 것과 같은 속성으로 0과 길이가 32 인 시퀀스를 취하고 0과 같은 길이의 시퀀스를 반환하는 함수 f를 어떻게 정의합니까?
관찰 : 32 비트의 경우 위의 질문에 대답 할 수 있다면 64 비트의 경우, 100 비트의 경우 등에도 대답 할 수 있습니다. 첫 32 비트에 f를 적용하면됩니다.
이제 2 비트 사례에 대한 질문에 대답 할 수 있다면 Voila!
그리고 그렇습니다. 처음 2 비트를 변경하면 충분합니다.
여기 의사 코드가 있습니다
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.
비고 : 2 단계와 3 단계를 함께 (a, b)-> (-b, a)로 합칠 수 있습니다. 익숙해 보이나요? 평면의 90도 회전과 -1의 제곱근에 의한 곱셈을 상기시켜야합니다.
긴 전주곡없이 의사 코드 만 제시하면 모자에서 토끼처럼 보일 것입니다. 어떻게 솔루션을 얻었는지 설명하고 싶었습니다.