35

我正在尝试解决projecteuler.net上的问题,但我一直遇到一些问题。

第一个是在 a 中存储大量元素的问题List<t>。在列表中存储大量数据时,我不断收到 OutOfMemoryException。

现在我承认我可能没有以最好的方式做这些事情,但是有没有办法定义应用程序可以消耗多少内存?

当我得到大约 100,000,000 个元素时,它通常会崩溃:S

其次,有些问题需要大量的数字相加。我使用 ulong 数据类型,我认为数字会变得非常大,但我仍然设法绕过最大支持的 int 并进入负数。

你对处理非常大的数字有什么建议吗?

4

11 回答 11

33

考虑System.Numerics.BigInteger

于 2008-11-10T20:28:41.070 回答
28

您需要使用一个使用一些基本数学原理的大数类来拆分这些操作。CodePoject 上的 C# BigInteger 库的这种实现似乎是最有希望的。这篇文章也很好地解释了海量运算的工作原理。

另请参阅: C# 中的大整数

于 2008-11-10T20:26:16.080 回答
11

就 Project Euler 而言,如果遇到 OutOfMemory 异常,您可能会找错树。从他们的网站:

每个问题都是按照“一分钟规则”设计的,这意味着尽管设计一个解决更困难问题的成功算法可能需要几个小时,但有效的实现将允许在功率适中的计算机上获得解决方案不到一分钟。

于 2008-11-10T20:39:25.383 回答
4

正如用户 Jakers 所说,如果您使用的是 Big Numbers,那么您可能做错了。

在我完成的 ProjectEuler 问题中,到目前为止没有一个需要大数数学。它更多地是关于找到合适的算法来避免大数字。

想要提示?在这里发布,我们可能会启动一个有趣的欧拉线程。

于 2009-01-16T17:25:27.317 回答
3

我假设这是 C#?F# 内置了处理这两个问题的方法(BigInt 类型和惰性序列)。

如果您愿意,可以使用 C# 中的两种 F# 技术。如果添加对核心 F# 程序集的引用,则 BigInt 类型可以从其他语言中合理使用。

惰性序列基本上只是语法友好的枚举器。将 100,000,000 个元素放在一个列表中并不是一个好计划,因此您应该重新考虑解决方案来解决这个问题。如果您不需要保留信息,请将其丢弃!如果重新计算它比存储它更便宜,那就扔掉它!

于 2008-11-10T20:28:44.813 回答
1

请参阅此线程中的答案。您可能需要使用可用的第三方大整数库/类之一,或者等待包含本机 BigInteger 数据类型的 C# 4.0。

于 2008-11-10T20:26:54.833 回答
1

至于定义应用程序将使用多少内存,您可以使用MemoryFailPoint类在执行操作之前检查可用内存。

这允许您在执行操作之前预先分配内存,因此您可以在运行之前检查操作是否会失败。

于 2008-11-11T08:55:33.243 回答
1

您不需要使用 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;
    }
}
于 2017-08-27T13:52:10.267 回答
0
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;
}
于 2018-05-20T16:15:51.423 回答
0

我不确定这是否是处理它的好方法,但我在我的项目中使用了以下内容。

对于每个项目,我有一个“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 如果“relevantDecimals”为 5,它将变为 1,00001,但如果“relevantDecimals”为 4,则根本不会改变。

这种方法使您能够毫无问题地处理 doubleLimit*10^intLimit 上的数字,并且至少对于 OOP 而言,跟踪起来并不难。

于 2018-12-14T13:38:16.783 回答
-1

如果你想处理非常大的数字,请看这里......

三木计算器

我不是为自己编写的专业程序员,有时,很抱歉不专业地使用 c#,但程序可以工作。我将不胜感激任何建议和纠正。我使用这个计算器从大约 58 位长的数字中生成 32 个字符的密码。由于程序以字符串格式添加数字,因此您可以对字符串变量的最大长度的数字进行计算。该程序使用长列表进行计算,因此可以计算更大的数字,可能是列表最大容量的 18 倍。

于 2022-03-03T16:34:49.553 回答