Подтвердить что ты не робот

Работа с невероятно большими номерами в .NET.

Я пытаюсь решить проблемы на projecteuler.net, но я все время сталкиваюсь с несколькими проблемами.

В первую очередь речь идет о хранении больших количеств элементов в List<t>. Я сохраняю OutOfMemoryException при хранении больших количеств в списке.

Теперь я признаю, что я, возможно, не делаю эти вещи наилучшим образом, но есть ли способ определить, сколько памяти может потреблять приложение?

Обычно он падает, когда я получаю около 100 000 000 элементов: S

Во-вторых, некоторые из вопросов требуют добавления массивных чисел. Я использую ulong тип данных, где я думаю, что число будет супер, но мне все же удается обернуть мимо наибольшего поддерживаемого int и получить отрицательные числа.

Есть ли у вас советы по работе с невероятно большими номерами?

4b9b3361

Ответ 2

Вам нужно использовать класс большого числа, который использует некоторые основные математические принципы для разделения этих операций. Эта реализация библиотеки С# BigInteger на CodePoject представляется наиболее перспективной. В статье есть некоторые хорошие объяснения того, как работают операции с массивными числами.

Также смотрите: Большие целые числа в С#

Ответ 3

Что касается Project Euler, вы можете лаять неправильное дерево, если вы используете исключения OutOfMemory. На своем веб-сайте:

Каждая проблема была разработана в соответствии с "одноминутным правилом", что означает, что, хотя для разработки успешного алгоритма с более сложными проблемами может потребоваться несколько часов, эффективная реализация позволит получить решение по скромной компьютер с питанием менее чем за минуту.

Ответ 4

Как сказал Jakers, если вы используете Big Numbers, возможно, вы делаете это неправильно.

Из проблем ProjectEuler, которые я сделал, до сих пор ни одна из них не требовала математики большого числа. Его больше о поиске правильного алгоритма, чтобы избежать больших чисел.

Хотите подсказки? Отправьте сюда, и у нас может возникнуть интересный поток Эйлера.

Ответ 5

Я предполагаю, что это С#? F # построил способы решения обеих этих проблем (тип BigInt и ленивые последовательности).

Вы можете использовать обе технологии F # из С#, если хотите. Тип BigInt можно использовать с других языков, если вы добавите ссылку на сборку ядра F #.

Ленивые последовательности в основном просто дружественные к синтаксису счетчикам. Внесение 100 000 000 элементов в список не является отличным планом, поэтому вы должны пересмотреть свои решения, чтобы обойти это. Если вам не нужно хранить информацию, выбросьте ее! Если дешевле перепроверить, чем хранить его, выбросьте его!

Ответ 6

См. ответы в этой теме . Вероятно, вам нужно использовать одну из сторонних больших целых библиотек/классов или ждать С# 4.0, которая будет включать собственный тип данных BigInteger.

Ответ 7

Чтобы определить, сколько памяти будет использовать приложение, вы можете проверить доступную память перед выполнением операции с помощью MemoryFailPoint класс.

Это позволяет предварительно распределять память перед выполнением операции, поэтому вы можете проверить, не завершится ли операция до ее запуска.

Ответ 8

Вам не нужно использовать BigInteger. Вы можете сделать это событие со строковым массивом чисел.

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;
    }
}

Ответ 9

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;
}

Ответ 10

Я не уверен, что это хороший способ справиться с этим, но я использую следующее в своем проекте.

У меня есть переменная "double theRelevantNumber" и "int PowerOfTen" для каждого элемента, а в моем соответствующем классе у меня есть переменная "int relatedDecimals".

Итак... когда встречаются большие числа, они обрабатываются так:

Сначала они меняются на x, yyy форму. Таким образом, если число 123456,789 было введено, а "powerOfTen" было 10, оно началось бы так:

theRelevantNumber = 123456,789 PowerOfTen = 10 Число было тогда: 123456,789 * 10 ^ 10

Затем он изменяется на: 1,23456789 * 10 ^ 15

Затем он округляется по количеству соответствующих десятичных знаков (например, 5) до 1,23456, а затем сохраняется вместе с "PowerOfTen = 15"

При сложении или вычитании чисел любое число вне соответствующих десятичных знаков игнорируется. Смысл, если вы берете:

1 * 10 ^ 15 + 1 * 10 ^ 10 он изменится на 1,00001, если значение "релевантныеДекали" равно 5, но не изменится, если значение "релевантныеДесятичные" равно 4.

Этот метод позволяет вам без проблем иметь дело с числами до doubleLimit * 10 ^ intLimit, и, по крайней мере, для ООП это не так сложно отследить.