2011-05-01 3 views
3

저는 C#에서 PI를 계산하고 있으며, 지금까지는 완벽한 데이터 유형을 제외하고는 완벽하지 않았습니다. 만약 내가 더블 사용하면 아래와 같은 결과를 얻을.C#에서 1 백만 + 자리를 보유 할 데이터 유형이 필요합니다.

K = 0, 델타 = 3,14176587301587, PI = 3,14176587301587

K = 1, 델타 = -0000173301147482709, PI = 3,14159257186839

K = 2, 델타 = 8 , 17736604635702E-08, PI = 3,14159265364205

K = 3, 델타 = -5,22954018637708E-11, PI = 3,14159265358975

K = 4, 델타 = 3,78997628626364E-14, PI = 3,14159265358979

k = 5, 델타 = -2,94045250629684E-17, 파이 = 3,14159265358979

네 번째 네 번 실행하면 알 수 있듯이 내 자리가 최대치가됩니다. 십진법은 조금 더 도움이되지만 많이 필요합니다. 내 알고리즘이 반복되고 추가됩니다.

문자열을 사용하는 방법에 대해 생각했지만 문제는 그 숫자를 유지할 데이터 형식이 없으면 문자열로 가져 오는 방법입니다.

와 나는 ... 난 그냥 궁금 사람들이 전에 이런 짓을했는지 어떤 조언을

감사를 알고있다!

+0

[C에서 # 임의 정밀도 소수점 (가능 중복 http://stackoverflow.com/questions/4523741/arbitrary-precision-decimals-in -c) – kennytm

+0

당신이 가지고있는 소수점을 사용함으로써 : 3.1415926535897932384626433832, 더 이상 –

답변

2

BigInteger을 사용하여 모든 부분을 소수점 이하로 저장할 수 있습니다.

+0

그것과 함께 prob가 필요합니다 .net 4.0 만약 내가 그것을 사용해야한다면 .. 내가 추측하지만 내가 선호하는 방법은 .net 2.0이고 최대 가능. –

+0

그리고 심지어 BigInteger는 불변이므로 많은 큰 객체를 할당해야하기 때문에 문제가 있습니다. – CodesInChaos

3

Swensen.BigInt.dll 어셈블리는 CodeProject에서 사용할 수 있습니다. .net 2.0 버전이 필요한 경우 here을 다운로드 할 수 있습니다.

+0

CodeProject를 CodeProject와 혼동했습니다 .-) –

+1

아, 죄송합니다. – oxilumin

0

사용이 코드는, 그것이 작품 매력

using System; 
using System.Text; 

class Solution 
{ 
    static void Main(string[] args) 
    { 
     BigNumber x = new BigNumber(100); 
     BigNumber y = new BigNumber(100); 
     x.ArcTan(16, 5); 
     y.ArcTan(4, 239); 
     x.Subtract(y); 
     stopWatch.Stop(); 
     Console.WriteLine(x.Print());  
     Console.ReadLine(); 
    } 
} 
public class BigNumber { 
    private UInt32[] number; 
    private int size; 
    private int maxDigits; 

    public BigNumber(int maxDigits) { 
     this.maxDigits = maxDigits; 
     this.size = (int) Math.Ceiling((float)maxDigits * 0.104) + 2; 
     number = new UInt32[size]; 
    } 
    public BigNumber(int maxDigits, UInt32 intPart) 
     : this(maxDigits) { 
     number[0] = intPart; 
     for (int i = 1; i < size; i++) { 
     number[i] = 0; 
     } 
    } 
    private void VerifySameSize(BigNumber value) { 
     if (Object.ReferenceEquals(this, value)) 
     throw new Exception("BigNumbers cannot operate on themselves"); 
     if (value.size != this.size) 
     throw new Exception("BigNumbers must have the same size"); 
    } 
    public void Add(BigNumber value) { 
     VerifySameSize(value); 

     int index = size - 1; 
     while (index >= 0 && value.number[index] == 0) 
     index--; 

     UInt32 carry = 0; 
     while (index >= 0) { 
     UInt64 result = (UInt64)number[index] + 
         value.number[index] + carry; 
     number[index] = (UInt32)result; 
     if (result >= 0x100000000U) 
      carry = 1; 
     else 
      carry = 0; 
     index--; 
     } 
    } 
    public void Subtract(BigNumber value) { 
     VerifySameSize(value); 

     int index = size - 1; 
     while (index >= 0 && value.number[index] == 0) 
     index--; 

     UInt32 borrow = 0; 
     while (index >= 0) { 
     UInt64 result = 0x100000000U + (UInt64)number[index] - value.number[index] - borrow; 
     number[index] = (UInt32)result; 
     if (result >= 0x100000000U) 
      borrow = 0; 
     else 
      borrow = 1; 
     index--; 
     } 
    } 
    public void Multiply(UInt32 value) { 
     int index = size - 1; 
     while (index >= 0 && number[index] == 0) 
     index--; 
    enter code here 
     UInt32 carry = 0; 
     while (index >= 0) { 
     UInt64 result = (UInt64)number[index] * value + carry; 
     number[index] = (UInt32)result; 
     carry = (UInt32)(result >> 32); 
     index--; 
     } 
    } 
    public void Divide(UInt32 value) { 
     int index = 0; 
     while (index < size && number[index] == 0) 
     index++; 

     UInt32 carry = 0; 
     while (index < size) { 
     UInt64 result = number[index] + ((UInt64)carry << 32); 
     number[index] = (UInt32) (result/(UInt64)value); 
     carry = (UInt32)(result % (UInt64)value); 
     index++; 
     } 
    } 
    public void Assign(BigNumber value) { 
     VerifySameSize(value); 
     for (int i = 0; i < size; i++) { 
     number[i] = value.number[i]; 
     } 
    } 

    public string Print() { 
     BigNumber temp = new BigNumber(maxDigits); 
     temp.Assign(this); 

     StringBuilder sb = new StringBuilder(); 
     sb.Append(temp.number[0]); 
     sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator); 

     int digitCount = 0; 
     while (digitCount < maxDigits) { 
     temp.number[0] = 0; 
     temp.Multiply(100000); 
     sb.AppendFormat("{0:D5}", temp.number[0]); 
     digitCount += 5; 
     } 

     return sb.ToString(); 
    } 
    public bool IsZero() { 
     foreach (UInt32 item in number) { 
     if (item != 0) 
      return false; 
     } 
     return true; 
    } 

    public void ArcTan(UInt32 multiplicand, UInt32 reciprocal) { 
     BigNumber X = new BigNumber(maxDigits, multiplicand); 
     X.Divide(reciprocal); 
     reciprocal *= reciprocal; 

     this.Assign(X); 

     BigNumber term = new BigNumber(maxDigits); 
     UInt32 divisor = 1; 
     bool subtractTerm = true; 
     while (true) { 
     X.Divide(reciprocal); 
     term.Assign(X); 
     divisor += 2; 
     term.Divide(divisor); 
     if (term.IsZero()) 
      break; 

     if (subtractTerm) 
      this.Subtract(term); 
     else 
      this.Add(term); 
     subtractTerm = !subtractTerm; 
     } 
    } 
}