2009-09-30 17 views
6

मुझे लगभग 100 तक संख्याओं के फैक्टोरियल की गणना करने की आवश्यकता है! यह निर्धारित करने के लिए कि this Wikipedia entry on Bayesian probability. के अनुसार सिक्का फ्लिप-शैली डेटा की एक श्रृंखला यादृच्छिक है, जैसा कि आप वहां देख सकते हैं, आवश्यक सूत्र में 3 फैक्टोरियल गणनाएं शामिल हैं (लेकिन, दिलचस्प बात यह है कि उनमें से दो तथ्यात्मक गणनाओं की गणना तीसरे के रास्ते में की जाती है)।लाइब्रेरी कॉल का उपयोग करके सी # में एक फैक्टोरियल की गणना कैसे कर सकता हूं?

मैंने this question here देखा, लेकिन मुझे लगता है कि पूर्णांक बहुत जल्दी उड़ाया जा रहा है। मैं एक समारोह भी बना सकता हूं जो फैक्टोरियल गणना के बारे में अधिक बुद्धिमान है (यानी, यदि मेरे पास 11 है!/(7! 3!), विकी उदाहरण के अनुसार, मैं (11 * 10 * 9 * 8)/3!), लेकिन यह मुझे समय से पहले अनुकूलन की याद दिलाता है, इस अर्थ में कि मैं इसे काम करना चाहता हूं, लेकिन मुझे गति (अभी तक) की परवाह नहीं है।

तो एक अच्छा सी # लाइब्रेरी क्या है जो मैं संभावना प्राप्त करने के लिए फैक्टोरियल की गणना करने के लिए कॉल कर सकता हूं? मुझे उन सभी उत्कृष्टताओं में दिलचस्पी नहीं है जो फैक्टरियल गणना में जा सकते हैं, मैं सिर्फ परिणाम को इस तरह से चाहता हूं कि मैं इसका उपयोग कर सकूं। गणित नामस्थान में एक फैक्टोरियल फ़ंक्शन नहीं दिखता है, इसलिए सवाल है।

उत्तर

7

आप Math.NET को आजमा सकते हैं - मैंने उस लाइब्रेरी का उपयोग नहीं किया है, लेकिन वे फैक्टोरियल और लॉगरिदमिक फैक्टोरियल सूचीबद्ध करते हैं।

+0

एक आकर्षण की तरह काम करता है, लिंक के लिए धन्यवाद! – mmr

+1

[Math] [http://numerics.mathdotnet.com/api/MathNet.Numerics/SpecialFunctions.htm#Factorial) [Math.NET न्यूमेरिक्स] में भी देखें (http://numerics.mathdotnet.com), जुड़े मैथ.NET इरिडियम पुस्तकालय के उत्तराधिकारी। –

4

इसी तरह के विषय पर previous question रहा है। किसी ने Fast Factorial Functions वेबसाइट को लिंक किया है, जिसमें कुशल एल्गोरिदम और यहां तक ​​कि सी # स्रोत कोड के कुछ स्पष्टीकरण शामिल हैं।

+0

यह now-- आदमी जाँच हो रही है बाहर, मैं वास्तव में चाहते हैं कुछ सबसे सन्निकटन-मई-नहीं-काम के लिए हर किसी के आधार पुस्तकालयों के हिस्से के रूप कार्यान्वयन थे। – mmr

+0

उस कोड के साथ समस्या यह है कि डाउनलोड जावा में सभी दिखाई देते हैं, और मुझे जावा से सी # में परिवर्तित करने के लिए काम में दिलचस्पी नहीं है। लेखक के पास शायद डाउनलोड करने के लिए सी # कोड है, लेकिन Math.Net समाधान परिणाम को एक डबल में डाल देता है, जो वास्तव में मुझे चाहिए। – mmr

3

क्या आप फैक्टोरियल, या द्विपदीय गुणांक की गणना करना चाहते हैं?

ऐसा लगता है जैसे आप द्विपक्षीय गुणांक की गणना करना चाहते हैं - खासकर जब आप 11 का उल्लेख करते हैं!/(7! 3!)।

ऐसी लाइब्रेरी हो सकती है जो आपके लिए यह कर सकती है, लेकिन एक (संभावित रूप से) प्रोग्रामर स्टैक ओवरफ़्लो पर जाकर, स्वयं को लिखने का कोई कारण नहीं है। यह बहुत जटिल नहीं है।

मेमोरी ओवरफ़्लो से बचने के लिए, परिणाम का मूल्यांकन न करें जब तक कि सभी सामान्य कारकों को हटाया न जाए।

इस एल्गोरिदम को अभी भी में सुधार करने की आवश्यकता है, लेकिन आपके पास यहां एक अच्छा एल्गोरिदम का आधार है। सर्वोत्तम परिणाम के लिए denominator मूल्यों को उनके प्रमुख कारकों में विभाजित करने की जरूरत है। जैसा कि यह खड़ा है, यह एन = 50 के लिए बहुत जल्दी चलेगा।

float CalculateBinomial(int n, int k) 
{ 
    var numerator = new List<int>(); 
    var denominator = new List<int>(); 
    var denominatorOld = new List<int>(); 

    // again ignore the k! common terms 
    for (int i = k + 1; i <= n; i++) 
     numerator.Add(i); 

    for (int i = 1; i <= (n - k); i++) 
    { 
     denominator.AddRange(SplitIntoPrimeFactors(i)); 
    } 

    // remove all common factors 
    int remainder;     
    for (int i = 0; i < numerator.Count(); i++) 
    { 
     for (int j = 0; j < denominator.Count() 
      && numerator[i] >= denominator[j]; j++) 
     { 
      if (denominator[j] > 1) 
      { 
       int result = Math.DivRem(numerator[i], denominator[j], out remainder); 
       if (remainder == 0) 
       { 
        numerator[i] = result; 
        denominator[j] = 1; 
       } 
      } 
     } 
    } 

    float denominatorResult = 1; 
    float numeratorResult = 1; 

    denominator.RemoveAll(x => x == 1); 
    numerator.RemoveAll(x => x == 1); 

    denominator.ForEach(d => denominatorResult = denominatorResult * d); 
    numerator.ForEach(num => numeratorResult = numeratorResult * num); 

    return numeratorResult/denominatorResult; 
} 

static List<int> Primes = new List<int>() { 2, 3, 5, 7, 11, 13, 17, 19, 
    23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 }; 

List<int> SplitIntoPrimeFactors(int x) 
{ 
    var results = new List<int>(); 
    int remainder = 0; 

    int i = 0; 
    while (!Primes.Contains(x) && x != 1) 
    { 
     int result = Math.DivRem(x, Primes[i], out remainder); 
     if (remainder == 0) 
     { 
      results.Add(Primes[i]); 
      x = result; 
      i = 0; 
     } 
     else 
     { 
      i++; 
     } 
    } 
    results.Add(x); 
    return results; 
} 

मैं अनुमान n कर सकते हैं = 110 k = 50 (रिटर्न 6x10^31), लेकिन नहीं चला सकते हैं एन = 120 k = 50.

+0

और क्या होता है जब n ~ = 50 और k ~ = 2? ओवरफ्लो!मुझे अनौपचारिक मामलों को संभालने के लिए कुछ रास्ता चाहिए। – mmr

+0

उस स्थिति में जब आप इंगित करते हैं तो आप n = 50 और k = 48 की गणना करते हैं। –

+0

ठीक है। 48 क्या है ?? क्या वह एक पूर्णांक में फिट होगा? क्योंकि उस मामले में आपका denominator क्या कर रहा है। – mmr

1
using System; 
//calculating factorial with recursion 
namespace ConsoleApplication2 
{ 
    class Program 
    { 
     long fun(long a) 
     { 
      if (a <= 1) 
      { 
       return 1;} 
      else 
      { 
       long c = a * fun(a - 1); 
       return c; 
      }} 

     static void Main(string[] args) 
     { 

      Console.WriteLine("enter the number"); 
      long num = Convert.ToInt64(Console.ReadLine()); 
      Console.WriteLine(new Program().fun(num)); 
      Console.ReadLine(); 
     } 
    } 
} 
+1

कृपया अन्य उत्तरों को पढ़ें। यह पर्याप्त समाधान नहीं है, क्योंकि लंबे समय तक 100 के करीब संख्या के आकार को संभालने की क्षमता नहीं है! इस प्रकार, कुछ अन्य विधि (जैसे स्टर्लिंग के अनुमान) को इसके बजाय उपयोग करने की आवश्यकता है। – mmr

1

में 5000 के भाज्य की गणना कर सकते निम्नलिखित 1 सेकेंड।

public class Number 
{ 
    #region Fields 
    private static long _valueDivision = 1000000000; 
    private static int _valueDivisionDigitCount = 9; 
    private static string _formatZeros = "000000000"; 
    List<long> _value; 
    #endregion 

    #region Properties 
    public int ValueCount { get { return _value.Count; } } 
    public long ValueAsLong 
    { 
     get 
     { 
      return long.Parse(ToString()); 
     } 
     set { SetValue(value.ToString()); } 
    } 
    #endregion 

    #region Constructors 
    public Number() 
    { 
     _value = new List<long>(); 
    } 
    public Number(long value) 
     : this() 
    { 
     SetValue(value.ToString()); 
    } 
    public Number(string value) 
     : this() 
    { 
     SetValue(value); 
    } 
    private Number(List<long> list) 
    { 
     _value = list; 
    } 
    #endregion 

    #region Public Methods 
    public void SetValue(string value) 
    { 
     _value.Clear(); 
     bool finished = false; 
     while (!finished) 
     { 
      if (value.Length > _valueDivisionDigitCount) 
      { 
       _value.Add(long.Parse(value.Substring(value.Length - _valueDivisionDigitCount))); 
       value = value.Remove(value.Length - _valueDivisionDigitCount, _valueDivisionDigitCount); 
      } 
      else 
      { 
       _value.Add(long.Parse(value)); 
       finished = true; 
      } 
     } 
    } 
    #endregion 

    #region Static Methods 
    public static Number operator +(Number c1, Number c2) 
    { 
     return Add(c1, c2); 
    } 
    public static Number operator *(Number c1, Number c2) 
    { 
     return Mul(c1, c2); 
    } 
    private static Number Add(Number value1, Number value2) 
    { 
     Number result = new Number(); 
     int count = Math.Max(value1._value.Count, value2._value.Count); 
     long reminder = 0; 
     long firstValue, secondValue; 
     for (int i = 0; i < count; i++) 
     { 
      firstValue = 0; 
      secondValue = 0; 
      if (value1._value.Count > i) 
      { 
       firstValue = value1._value[i]; 
      } 
      if (value2._value.Count > i) 
      { 
       secondValue = value2._value[i]; 
      } 
      reminder += firstValue + secondValue; 
      result._value.Add(reminder % _valueDivision); 
      reminder /= _valueDivision; 
     } 
     while (reminder > 0) 
     { 
      result._value.Add(reminder % _valueDivision); 
      reminder /= _valueDivision; 
     } 
     return result; 
    } 
    private static Number Mul(Number value1, Number value2) 
    { 
     List<List<long>> values = new List<List<long>>(); 
     for (int i = 0; i < value2._value.Count; i++) 
     { 
      values.Add(new List<long>()); 
      long lastremain = 0; 
      for (int j = 0; j < value1._value.Count; j++) 
      { 
       values[i].Add(((value1._value[j] * value2._value[i] + lastremain) % _valueDivision)); 
       lastremain = ((value1._value[j] * value2._value[i] + lastremain)/_valueDivision); 
       //result.Add((); 
      } 
      while (lastremain > 0) 
      { 
       values[i].Add((lastremain % _valueDivision)); 
       lastremain /= _valueDivision; 
      } 
     } 
     List<long> result = new List<long>(); 
     for (int i = 0; i < values.Count; i++) 
     { 
      for (int j = 0; j < i; j++) 
      { 
       values[i].Insert(0, 0); 
      } 
     } 
     int count = values.Select(list => list.Count).Max(); 
     int index = 0; 
     long lastRemain = 0; 
     while (count > 0) 
     { 
      for (int i = 0; i < values.Count; i++) 
      { 
       if (values[i].Count > index) 
        lastRemain += values[i][index]; 
      } 
      result.Add((lastRemain % _valueDivision)); 
      lastRemain /= _valueDivision; 
      count -= 1; 
      index += 1; 
     } 
     while (lastRemain > 0) 
     { 
      result.Add((lastRemain % _valueDivision)); 
      lastRemain /= _valueDivision; 
     } 
     return new Number(result); 
    } 
    #endregion 

    #region Overriden Methods Of Object 
    public override string ToString() 
    { 
     string result = string.Empty; 
     for (int i = 0; i < _value.Count; i++) 
     { 
      result = _value[i].ToString(_formatZeros) + result; 
     } 
     return result.TrimStart('0'); 
    } 
    #endregion 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Number number1 = new Number(5000); 
     DateTime dateTime = DateTime.Now; 
     string s = Factorial(number1).ToString(); 
     TimeSpan timeSpan = DateTime.Now - dateTime; 
     long sum = s.Select(c => (long) (c - '0')).Sum(); 
    } 
    static Number Factorial(Number value) 
    { 
     if(value.ValueCount==1 && value.ValueAsLong==2) 
     { 
      return value; 
     } 
     return Factorial(new Number(value.ValueAsLong - 1)) * value; 
    } 
} 
+1

यह मेरे कंप्यूटर पर 1 सेकंड में नहीं चलता है;) –

संबंधित मुद्दे

 संबंधित मुद्दे