lavorare con numeri incredibilmente grandi in .NET

Sto cercando di risolvere i problemi su projecteuler.net ma continuo a incontrare un paio di problemi.

Il primo è una questione di memorizzazione di grandi quantità di elementi in un List . Continuo a ricevere OutOfMemoryException quando si memorizzano grandi quantità nell’elenco.

Ora ammetto che potrei non fare queste cose nel modo migliore ma, c’è un modo per definire la quantità di memoria che l’app può consumare?

Di solito si blocca quando ottengo 100.000.000 di elementi: S

In secondo luogo, alcune delle domande richiedono l’aggiunta di numeri massivi. Io uso un tipo di dati ulong dove penso che il numero diventerà super grande, ma riesco ancora a racchiudere il più grande int supportato e entrare in numeri negativi.

    Hai qualche consiglio per lavorare con numeri incredibilmente grandi?

    Considera System.Numerics.BigInteger .

    È necessario utilizzare una class numerica di grandi dimensioni che utilizza principi matematici di base per suddividere queste operazioni. Questa implementazione di una libreria C # BigInteger su CodePoject sembra essere la più promettente. L’articolo ha alcune buone spiegazioni su come funzionano anche le operazioni con numeri massivi.

    Vedi anche: Big interi in C #

    Per quanto riguarda Project Euler, potresti sbatterti nell’albero sbagliato se stai battendo le eccezioni OutOfMemory. Dal loro sito web:

    Ogni problema è stato progettato in base a una “regola di un minuto”, il che significa che sebbene possano essere necessarie diverse ore per progettare un algoritmo di successo con problemi più complessi, un’implementazione efficiente consentirà di ottenere una soluzione su un computer alimentato in modo modesto meno di un minuto.

    Come ha detto l’utente Jakers, se stai usando i Big Numbers, probabilmente stai sbagliando.

    Dei problemi di ProjectEuler che ho fatto, nessuno ha richiesto la matematica di numeri grandi finora. Si tratta più di trovare l’algoritmo corretto per evitare i numeri grandi.

    Vuoi suggerimenti? Pubblica qui e potremmo avere un interessante thread di Euler avviato.

    Presumo che questo sia C #? F # ha un modo per gestire entrambi questi problemi (tipo BigInt e sequenze lazy).

    Puoi usare entrambe le tecniche F # da C #, se vuoi. Il tipo BigInt è ragionevolmente utilizzabile da altre lingue se si aggiunge un riferimento all’assembly F # di base.

    Le sequenze pigre sono fondamentalmente solo enumeratori sintattici. Mettere 100.000.000 di elementi in una lista non è un grande piano, quindi dovresti riconsiderare le tue soluzioni per aggirarle. Se non hai bisogno di tenere le informazioni in giro, buttale via! Se è più economico ricalcolarlo che archiviarlo, buttalo via!

    Vedi le risposte in questa discussione . Probabilmente è necessario utilizzare una delle librerie / classi di interi interi di terze parti disponibili o attendere C # 4.0 che includa un tipo di dati BigInteger nativo.

    Per quanto riguarda la quantità di memoria che un’app utilizzerà, è ansible controllare la memoria disponibile prima di eseguire un’operazione utilizzando la class MemoryFailPoint .

    Ciò consente di preallocare la memoria prima di eseguire l’operazione, in modo da poter verificare se un’operazione fallirà prima di eseguirla.

    Non è necessario utilizzare BigInteger Puoi fare questo evento con una serie di numeri di stringhe.

     class Solution { static void Main(String[] args) { int n = 5; string[] unsorted = new string[6] { "3141592653589793238","1", "3", "5737362592653589793238", "3", "5" }; string[] result = SortStrings(n, unsorted); foreach (string s in result) Console.WriteLine(s); Console.ReadLine(); } static string[] SortStrings(int size, string[] arr) { Array.Sort(arr, (left, right) => { if (left.Length != right.Length) return left.Length - right.Length; return left.CompareTo(right); }); return arr; } } 
     string Add(string s1, string s2) { bool carry = false; string result = string.Empty; if (s1.Length < s2.Length) s1 = s1.PadLeft(s2.Length, '0'); if(s2.Length < s1.Length) s2 = s2.PadLeft(s1.Length, '0'); for(int i = s1.Length-1; i >= 0; i--) { var augend = Convert.ToInt64(s1.Substring(i,1)); var addend = Convert.ToInt64(s2.Substring(i,1)); var sum = augend + addend; sum += (carry ? 1 : 0); carry = false; if(sum > 9) { carry = true; sum -= 10; } result = sum.ToString() + result; } if(carry) { result = "1" + result; } return result; }