2008-09-15 10 views
25

제네릭을 사용하여 데이터 저장을 위해 선택한 기본 유형에 의존하지 않는 수학 라이브러리를 만드는 방법은 있습니까?C#의 제네릭을 사용하여 수학 라이브러리 만들기

즉, Fraction 클래스를 작성한다고 가정 해 보겠습니다. 분수는 두 개의 int 또는 두 개의 double 또는 기타 등등으로 표현할 수 있습니다. 중요한 것은 4 개의 산술 연산이 잘 정의되어 있다는 것입니다. 따라서 Fraction<int> frac = new Fraction<int>(1,2) 및/또는 Fraction<double> frac = new Fraction<double>(0.1, 1.0)을 작성하고 싶습니다.

불행히도 네 가지 기본 작업 (+, -, *, /)을 나타내는 인터페이스가 없습니다. 아무도 실행 가능하고 실현 가능한 방법을 찾았습니까?

답변

25

이 상대적으로 통증이 추상적 밖으로 운영하는 방법입니다.

사용하는 형식을 구현하지 못하면 컴파일 타임이 아닌 런타임에 오류가 발생합니다. MathProvider<T> 구현의 정의는 항상 동일 할 것입니다 (나쁘다). 나는 C#에서이 작업을 피하고 F # 또는이 추상화 수준에 더 적합한 다른 언어를 사용하는 것이 좋습니다.

편집 :Fraction<T>에 대한 더하기 및 빼기의 고정 된 정의. 또 다른 흥미롭고 간단한 것은 추상 구문 트리에서 작동하는 MathProvider를 구현하는 것입니다. 이 아이디어는 자동 차별화와 같은 일을 즉시 지적합니다 : http://conal.net/papers/beautiful-differentiation/

+0

좋은 깨끗한 :) –

+1

일반적인 방법으로 나는 MathProvider가 인터페이스로 만들어 져야한다고 생각하고 일반적인 인터페이스 방법으로 빼거나 Extension Method로 구현 될 수 있다고 생각한다. 그것은 다른 한편으로는 그것을 무시하는 것을 허용하지 않을 것입니다. – dalle

+0

당신의 솔루션의 성능에 대해 궁금합니다 ... 모든 것이 인라인 된 경우에만 효과가 있습니다 ... –

1

먼저 클래스는 제네릭 매개 변수를 primitives (public class Fraction 인 경우 T : struct, new())로 제한해야합니다.

두 번째로, 컴파일러가 울지 않고 한 유형에서 다른 유형으로 캐스팅을 처리 할 수 ​​있도록 implicit cast overloads을 작성해야 할 것입니다.

세 가지 유형의 분수를 결합 할 때 인터페이스를 더 유연하게 만들기 위해 네 가지 기본 연산자를 오버로드 할 수 있습니다.

마지막으로 산술 오버 및 언더 플로우를 처리하는 방법을 고려해야합니다. 좋은 라이브러리는 오버 플로우를 처리하는 방법에 매우 명시 적입니다. 그렇지 않으면 다른 분수 유형의 연산 결과를 신뢰할 수 없습니다.

+1

문제는 구조체에 더하기 연산자가 정의되어 있지 않기 때문에 합계를 계산할 수 없다는 것입니다. – Sklivvz

+0

http://msdn.microsoft.com/en-us/library/aa691324(VS.71).aspx "사용자 정의 구현은 클래스 및 구조체에 연산자 선언을 포함하여 도입 될 수 있습니다." – Will

2

다음은 제네릭 형식과 관련된 미묘한 문제입니다. 알고리즘이 나눗셈을 포함한다고 가정하면 방정식 시스템을 풀기 위해 가우스 제거가 발생합니다. 정수를 전달하면 정수을 수행 할 것이기 때문에 잘못된 답을 얻을 수 있습니다. 그러나 정수 값을 가진 이중 인수를 전달하면 올바른 대답을 얻을 수 있습니다.

콜레트산 인수 분해에서와 마찬가지로 제곱근에서 동일한 문제가 발생합니다. 정수 매트릭스를 인수 분해하는 것은 잘못 될 것입니다. 반면에 정수 값을 갖는 이중 인자의 매트릭스를 인수 분해하는 것은 문제가되지 않습니다.