수학은 어때요?.NET Framework에 구현된 Pow()?
저는 계산을 위한b 효율적인 접근법을 찾고 있었습니다.a = 2
그리고.b = 50
시작하기 위해, 저는 의 구현을 살펴보기로 결정했습니다.Math.Pow()
기능.하지만 .NET Reflector에서 찾은 것은 다음과 같습니다.
[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern double Pow(double x, double y);
전화를 걸 때 내부 상황을 확인할 수 있는 리소스는 무엇입니까?Math.Pow()
기능?
MethodImplOptions.InternalCall
즉, 이 방법은 C++로 작성된 CLR에서 실제로 구현됩니다.Just-in-Time 컴파일러는 내부적으로 구현된 메서드로 테이블을 참조하고 C++ 함수에 대한 호출을 직접 컴파일합니다.
코드를 보려면 CLR의 소스 코드가 필요합니다.SSCLI20 분포에서 이를 확인할 수 있습니다..NET 2.0 시간대에 작성되었으며 다음과 같은 낮은 수준의 구현을 찾았습니다.Math.Pow()
CLR의 이후 버전에 대해서는 여전히 대체로 정확합니다.
조회 테이블은 clr/src/vm/ecall.cpp에 있습니다.과 Math.Pow()
다음과 같이 표시됩니다.
FCFuncStart(gMathFuncs)
FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
FCFuncElement("Exp", COMDouble::Exp)
FCFuncElement("Pow", COMDouble::Pow)
// etc..
FCFuncEnd()
"로 합니다.COMDouble" 파일은 clr/src/classlibative/float/compfloat.cpp입니다.코드는 생략하겠습니다. 직접 확인해 보세요.을 CRT라고 .pow()
.
유일하게 흥미로운 구현 세부사항은 표의 FC Intrinsic 매크로입니다.이것은 지터가 기능을 내재적으로 구현할 수 있다는 암시입니다.즉, 함수 호출을 부동 소수점 기계 코드 명령으로 대체합니다.이 경우에는 그렇지 않습니다.Pow()
FPU 명령이 없습니다.하지만 다른 간단한 수술들은 확실히 그렇습니다.주목할 점은 이것이 C#의 부동소수점 연산을 C++의 동일한 코드보다 상당히 빠르게 만들 수 있다는 것입니다. 그 이유를 위해 이 답변을 확인하십시오.
참고로 Visual Studio vc/crt/src 디렉터리의 전체 버전이 있는 경우에도 CRT의 소스 코드를 사용할 수 있습니다.당신은 벽에 부딪힐 것입니다.pow()
하지만 마이크로소프트는 인텔로부터 그 코드를 구입했습니다.Intel 엔지니어보다 더 나은 작업을 수행할 가능성은 거의 없습니다.비록 내가 그것을 시도했을 때 내 고등학교 책의 정체성은 두 배나 빨랐지만:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
그러나 3개의 부동 소수점 연산에서 오류가 누적되고 Pow()가 가지고 있는 이상한 도메인 문제를 처리하지 않기 때문에 진정한 대체는 아닙니다.0^0과 -Infinity가 어떤 멱급수로 상승한 것처럼.
한스 패상의 대답은 훌륭하지만, 저는 만약에b
다음은 정수입니다.a^b
이진 분해를 사용하여 매우 효율적으로 계산할 수 있습니다.다음은 헨리 워렌의 '해커즈 딜라이트'에서 수정된 버전입니다.
public static int iexp(int a, uint b) {
int y = 1;
while(true) {
if ((b & 1) != 0) y = a*y;
b = b >> 1;
if (b == 0) return y;
a *= a;
}
}
그는 이 연산이 모든 b < 15에 대해 최적(최소한의 산술 연산 또는 논리 연산을 수행함)임을 언급합니다.또한 계산할 최적의 요인 시퀀스를 찾는 일반적인 문제에 대한 알려진 해결책은 없습니다.a^b
광범위한 검색 이외의 다른 검색을 위해.NP-Hard 문제입니다.기본적으로 이는 이진 분해가 얻는 것만큼 좋다는 것을 의미합니다.
무료로 사용할 수 있는 C 버전이 표시된다면, 그것은 당신이 기대하는 것처럼 보이지 않습니다..NET 버전을 찾는 것은 당신에게 큰 도움이 되지 않을 것입니다. 왜냐하면 당신이 해결하고 있는 문제(즉, 정수가 있는 문제)는 크기 순서가 더 단순하고 제곱 알고리즘에 의한 지수화로 C# 코드의 몇 줄로 해결할 수 있기 때문입니다.
답을 검토한 결과, 백그라운드 계산에 대해 많은 것을 알게 된 내용은 다음과 같습니다.광범위한 테스트 적용 사례가 있는 코딩 플랫폼에서 몇 가지 해결 방법을 시도해 본 결과 매우 효과적인 방법을 찾았습니다(솔루션 3).
public double MyPow(double x, int n) {
double res = 1;
/* Solution 1: iterative : TLE(Time Limit Exceeded)
double res = 1;
var len = n > 0 ? n : -n;
for(var i = 0; i < len; ++i)
res *= x;
return n > 0 ? res : 1 / res;
*/
/* Solution 2: recursive => stackoverflow exception
if(x == 0) return n > 0 ? 0 : 1 / x;
if(n == 1) return x;
return n > 0 ? x * MyPow(x, n - 1) : (1/x) * MyPow(1/x, -n);
*/
//Solution 3:
if (n == 0) return 1;
var half = MyPow(x, n / 2);
if (n % 2 == 0)
return half * half;
else if (n > 0)
return half * half * x;
else
return half * half / x;
/* Solution 4: bitwise=> TLE(Time Limit Exceeded)
var b = n > 0 ? n : -n;
while(true) {
if ((b & 1) != 0)
res *= x;
b = b >> 1;
if (b == 0) break;
x *= x;
}
return n > 0 ? res : 1 / res;
*/
}
리트코드에서 허용되는 답변:
public class Solution {
public double MyPow(double x, int n) {
if(n==0) return 1;
long abs = Math.Abs((long)n);
var result = pow(x, abs);
return n > 0 ? result : 1/result;
}
double pow(double x, long n){
if(n == 1) return x;
var result = pow(x, n/2);
result = result * result * (n%2 == 1? x : 1);
return result;
}
}
언급URL : https://stackoverflow.com/questions/8870442/how-is-math-pow-implemented-in-net-framework
'bestsource' 카테고리의 다른 글
사용 MongoClient(Mongoose 4.11.0)를 설정하는 방법은 무엇입니까? (0) | 2023.05.29 |
---|---|
ASP.NET MVC Core의 드롭다운 목록에 열거형 사용 (0) | 2023.05.29 |
Angular - 구성 요소에서 module.id 의 의미는 무엇입니까? (0) | 2023.05.29 |
ExecuteScalar, ExecuteReader 및 ExecuteNonQuery의 차이점은 무엇입니까? (0) | 2023.05.29 |
Visual Studio 컴파일 오류인 "프로세서 아키텍처 간 불일치"를 해결하려면 어떻게 해야 합니까? (0) | 2023.05.29 |