2010-05-11 5 views
1

this 문서에서 도움이 필요합니다. 코드는 다음과 같습니다.C에서 Java로 코드를 번역 할 때 도움이 필요합니다.

float InvSqrt(float x){ // line 0 
    float xhalf = 0.5f * x; 
    int i = *(int*)&x; // store floating-point bits in integer 
    i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method 
    x = *(float*)&i; // convert new bits into float 
    x = x*(1.5f - xhalf*x*x); // One round of Newton's method 
    return x; 
} 

... 나는 C 또는 C++인지 여부조차 알 수 없습니다. [좋아, 분명히 C, 고마워.] 누군가 나를 자바로 번역 할 수 있을까? 저를 혼란스럽게하는 것은 2 번과 4 번 라인입니다.

+0

둘 다입니다. 그것은 기술적으로 C (지진 엔진은 C 언어로 작성되었습니다.)이지만 합법적 인 C++이고 C++ 컴파일러에서 컴파일됩니다. –

+2

목표는 역 제곱근을 얻거나 위의 코드가 Java에서 어떻게 보이는지 확인하는 것입니다. – extraneon

+0

@ 마이클 그것은 지진 코드로 보이지 않는, 마법의 상수가 조금 떨어져있는 것 같습니다 :) – extraneon

답변

10

당신은이 방법을 사용하려면 (주의 : 이것은 테스트되지 않았습니다!)

float InvSqrt(float x){ // line 0 
    float xhalf = 0.5f * x; 
    int i = Float.floatToIntBits(x); // store floating-point bits in integer 
    i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method 
    x = Float.intBitsToFloat(i); // convert new bits into float 
    x = x*(1.5f - xhalf*x*x); // One round of Newton's method 
    return x; 
} 
+0

@Vuntic : stackoverflow의'strictfp'에 대한 많은 Q/As가 있습니다. 나는 그 문제를 너무 자세하게 알지 못한다. 나는 그것이 뭔가 중요한 것일 수도 있다는 직감을 가지고있다. 아니면 무의미한 것일 수도 있습니다.) – polygenelubricants

2

주석은 C++ 스타일이지만 주석은 C입니다.

코드에서 수행하는 작업에는 비트 수준에서 부동 소수점 값이 저장되는 방식에 대한 정보가 포함됩니다. "마법의 숫자"0x5f3759d5은 특정 값과 관련이 있습니다.

x의 주소가 역 참조되기 때문에 i이 초기화 될 때 부동 소수점 x 값의 비트가 액세스됩니다. 따라서 i에는 부동 소수점 값의 처음 32 비트가로드됩니다. 다음 줄에 x 내용이 i으로 작성되어 작업 근사값을 업데이트합니다.

John Carmack이 ID의 오픈 소스 Quake 엔진을 사용하여이 코드를 릴리스했을 때이 코드가 널리 사용됨을 읽었습니다. 이 코드의 목적은 그래픽 엔진의 조명 계산에 사용되는 1/Sqrt (x)를 빠르게 계산하는 것입니다.

이 코드를 위에서 설명한대로 "유형 punning"을 사용하기 때문에 Java로 직접 변환 할 수 없었습니다. 마치 int 인 것처럼 메모리에서 float에 액세스 할 때. Java는 그러한 종류의 활동을 방지하지만, 다른 사람들이 지적했듯이, Float 객체는 그 주위에 메소드를 제공합니다.

C에서이 이상한 구현을 사용하려는 목적은 매우 빠릅니다. 그것이 쓰여졌을 때, 나는이 방법으로 큰 발전이 일어 났을 것이라고 상상한다. 부동 소수점 연산이 빨라지면 그 차이가 현재 가치가 있는지 궁금합니다.

Java 메소드를 사용하여 float를 정수 비트로 변환 한 후 다시 제곱근에 대한 Java 수학 함수를 직접 사용하여 역 제곱근을 계산하는 것보다 속도가 느릴 수 있습니다. strictfp

그리고이있을 수있는 문제 등

그것은 거의 같은 뭔가 :

+0

float를 Java에서 정수로 처리 할 수 ​​있습니다 - 아래에 나오는 내 의견을 참조하십시오. 편집 - 마이클이 나를 너무 이길 - 그의 모습을 보아라! :) – corsiKa

+0

float를 int로 처리하는 것은 OP가 원하는 것이 아닙니다. 그건자를거야. 다른 사람들이 설명하는 것처럼 그들은 floattointbits 메서드가 필요합니다. –

+0

@ 브라이언, 그 의미는 - 그것이 내가 할 일이었습니다. 마이클이 저를 너무 때렸습니다. – corsiKa

7

이 라인들은 floatint 사이를 비트 패턴으로 변환하는 데 사용됩니다. 자바는 그것에 대한 java.lang.Float에 정적 메소드를 가지고 있습니다 - 그 외 모든 것은 동일합니다.

static float InvSqrt(float x) { // line 0 
    float xhalf = 0.5f * x; 
    int i = Float.floatToIntBits(x); // store floating-point bits in integer 
    i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method 
    x = Float.intBitsToFloat(i); // convert new bits into float 
    x = x * (1.5f - xhalf * x * x); // One round of Newton's method 
    return x; 
} 
+0

'strictfp'에 대한 의견이 있으십니까? 이 문맥에서 문제가 되는가? 우리가 비트 등을 가지고 놀고 있기 때문에? – polygenelubricants

+1

이론적으로'strictfp'는 보장 된 방식으로 결과를 일관되게 만듭니다. 필요 여부는 원래 코드가 특정 부동 소수점 구현에 의존하는지 여부에 따라 다릅니다. –

+1

@ polygenelubricants : strictfp가 다른 곳보다 더 많은 이슈가 될 것이라고 생각하지 않습니다. "비트로 연주"부분은 값이 부동 소수점 산술을 수행하기 전에 완전히 발생합니다. –

0

관심있는 라인은 매우 간단합니다. 2 행은 부동 소수점 x의 바이트를 IEEE754와 같은 일부 부동 소수점 표현으로 가져 와서 정확하게 정수로 저장합니다. 정수와 부동 소수점은 바이트 형식으로 다르게 표현되므로 완전히 다른 수를 얻게됩니다.4 번 줄은 그 반대이며 float에 해당 int의 바이트를 다시 전송합니다.

1

좋아요. 저는 C를 알고 있기 때문에 여기에 사지가 있습니다.하지만 Java는 알지 못합니다.

문자 그대로이 C 코드를 Java로 다시 작성하면 문제가 발생합니다. C에서도 코드는 이식 할 수 없습니다. 다른 것들 사이에 의존 : 부동 소수점의 크기. 정수의 크기입니다. 부동 소수점 숫자의 내부 표현입니다. 부동 소수점 숫자와 정수의 바이트 정렬입니다. 논리 오른쪽 시프트 을 사용하여 오른쪽 시프트 (즉, i >> 1)가 구현되었습니다 (이는 상위 순서 1 비트가 인 정수에서 1로 시프트하므로 더 이상 을 2로 나눈 값이 아닙니다) .

기계 코드가 이 아니고 바이트 코드로 Java가 컴파일되는 것을 이해합니다. 바이트 코드 인터프리터의 구현자는 바이트 코드의 스펙을 기반으로 한 가정과 현명한 입력 소스 코드에서 컴파일러가 출력 한 내용을 이해하는 을 사용하여 조정합니다.

이와 같은 해킹은 우산 "현명한 입력 소스"에 해당하지 않습니다.

통역사가 C 해킹으로 더 빨리 수행 할 것이라고 기대할 이유가 없습니다. 실제로는 더 좋은 기회가 있습니다. 더 느립니다.

내 조언은 : IGNORE C 코드.

자바 중심의 효율성을 찾으십시오.

는 C 해킹의 개념은 :

대략 1/제곱 (x)의 부동 소수점 숫자의 내부 표현은 이미 수 중에서 깨진 지수를 가지고 지식 지수를 활용하여 (X)/2 이미 지수 (x)가있는 경우 이 root (x)보다 더 빠릅니다.

그러면 해킹은 newton의 방법 을 한 번 반복하여 근사값의 오류를 줄입니다. 나는 한 번의 반복으로 오류를 무언가 허용치까지 줄일 수 있다고 이라고 추정한다.

은 아마도 자바, 의 개념을 보증 조사하지만 세부 사항은 JAVA가 구현되는 방법 의 친밀한 지식에 따라 달라집니다, C는 구현되지 방법에 대해 설명합니다.

+0

C에서는 코드가 이식 불가능할 수 있지만 Java에서 완벽하게 안전합니다. 언급 한 모든 사항이 여기에 자세히 지정되어 있기 때문입니다. 제한된 정밀도 만 있으면 필요한만큼 Java에서 훨씬 빠르지 않을 이유가 없습니다. –

+0

안전하고 빠르며 * Java * 코드를 게시하지 않는 한 사용자의 의견은 배경 잡음 일뿐입니다. C 코드는 Java 소비가 아닙니다. 요점은 : Java 구현 세부 사항을 이해하기 위해 C 구현 세부 사항을 살펴 보지 마십시오. 그들은 다를 것입니다. – pbernatchez

관련 문제