【问题标题】:working with incredibly large numbers in .NET在 .NET 中处理令人难以置信的大量数字
【发布时间】:2022-03-04 00:34:49
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 在 .NET 4.0 中,System.Numerics.BigInteger 处理大数。

标签: c# .net biginteger largenumber


【解决方案1】:

【讨论】:

    【解决方案2】:

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

    另见: Big integers in C#

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 大声笑,是的。我不是超级数学家。虽然我希望能学到一些东西
      • 你可以通过一些基本的数论和集合论很好地解决问题。阅读有关许多素数问题的米勒拉宾素数测试。
      【解决方案4】:

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

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

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

      【讨论】:

      • 从原始帖子超过一年半的随机投票,没有评论?多么好奇!
      • ProjectEuler 更多的是关于聪明的数学而不是聪明的编程,我真的觉得这有点烦人。
      【解决方案5】:

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

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

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

      【讨论】:

        【解决方案6】:

        thread 中查看答案。您可能需要使用可用的第三方大整数库/类之一,或者等待包含原生 BigInteger 数据类型的 C# 4.0。

        【讨论】:

          【解决方案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;
                }
            }
            

            【讨论】:

            • 但是如何添加它们?
            • Abhilash Virat,你能解释一下 Array.Sort () Lamda 函数是如何工作的吗?我没有关注它。
            【解决方案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,它将像这样开始:

              相关编号 = 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 而言,跟踪起来并不难。

              【讨论】:

                【解决方案11】:

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

                MIKI Calculator

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

                【讨论】:

                • 这不是答案
                猜你喜欢
                • 1970-01-01
                • 2013-10-10
                • 1970-01-01
                • 2019-06-05
                • 1970-01-01
                • 2013-01-06
                • 2018-08-05
                • 2011-07-20
                • 2021-11-15
                相关资源
                最近更新 更多