简体   繁体   English

在 .NET 中处理令人难以置信的大量数字

[英]working with incredibly large numbers in .NET

I'm trying to work through the problems on projecteuler.net but I keep running into a couple of problems.我正在尝试解决projecteuler.net上的问题,但我一直遇到一些问题。

The first is a question of storing large quanities of elements in a List<t> .第一个是在List<t>中存储大量元素的问题。 I keep getting OutOfMemoryException's when storing large quantities in the list.在列表中存储大量数据时,我不断收到 OutOfMemoryException。

Now I admit I might not be doing these things in the best way but, is there some way of defining how much memory the app can consume?现在我承认我可能没有以最好的方式做这些事情,但是有没有办法定义应用程序可以消耗多少内存?

It usually crashes when I get abour 100,000,000 elements :S当我得到大约 100,000,000 个元素时,它通常会崩溃:S

Secondly, some of the questions require the addition of massive numbers.其次,有些问题需要大量的数字相加。 I use ulong data type where I think the number is going to get super big, but I still manage to wrap past the largest supported int and get into negative numbers.我使用 ulong 数据类型,我认为数字会变得非常大,但我仍然设法绕过最大支持的 int 并进入负数。

Do you have any tips for working with incredibly large numbers?你对处理非常大的数字有什么建议吗?

You need to use a large number class that uses some basic math principals to split these operations up.您需要使用一个使用一些基本数学原理的大数类来拆分这些操作。 This implementation of a C# BigInteger library on CodePoject seems to be the most promising. CodePoject 上的 C# BigInteger 库的这种实现似乎是最有希望的。 The article has some good explanations of how operations with massive numbers work, as well.这篇文章也很好地解释了海量运算的工作原理。

Also see: Big integers in C#另请参阅: C# 中的大整数

As far as Project Euler goes, you might be barking up the wrong tree if you are hitting OutOfMemory exceptions.就 Project Euler 而言,如果遇到 OutOfMemory 异常,您可能会找错树。 From their website:从他们的网站:

Each problem has been designed according to a "one-minute rule", which means that although it may take several hours to design a successful algorithm with more difficult problems, an efficient implementation will allow a solution to be obtained on a modestly powered computer in less than one minute.每个问题都是按照“一分钟规则”设计的,这意味着尽管设计一个解决更困难问题的成功算法可能需要几个小时,但有效的实现将允许在功率适中的计算机上获得解决方案不到一分钟。

As user Jakers said, if you're using Big Numbers, probably you're doing it wrong.正如用户 Jakers 所说,如果您使用的是 Big Numbers,那么您可能做错了。

Of the ProjectEuler problems I've done, none have required big-number math so far.在我完成的 ProjectEuler 问题中,到目前为止没有一个需要大数数学。 Its more about finding the proper algorithm to avoid big-numbers.它更多地是关于找到合适的算法来避免大数字。

Want hints?想要提示? Post here, and we might have an interesting Euler-thread started.在这里发布,我们可能会启动一个有趣的欧拉线程。

I assume this is C#?我假设这是 C#? F# has built in ways of handling both these problems (BigInt type and lazy sequences). F# 内置了处理这两个问题的方法(BigInt 类型和惰性序列)。

You can use both F# techniques from C#, if you like.如果您愿意,可以使用 C# 中的两种 F# 技术。 The BigInt type is reasonably usable from other languages if you add a reference to the core F# assembly.如果添加对核心 F# 程序集的引用,则 BigInt 类型可以从其他语言中合理使用。

Lazy sequences are basically just syntax friendly enumerators.惰性序列基本上只是语法友好的枚举器。 Putting 100,000,000 elements in a list isn't a great plan, so you should rethink your solutions to get around that.将 100,000,000 个元素放在一个列表中并不是一个好计划,因此您应该重新考虑解决方案来解决这个问题。 If you don't need to keep information around, throw it away!如果您不需要保留信息,请将其丢弃! If it's cheaper to recompute it than store it, throw it away!如果重新计算它比存储它更便宜,那就扔掉它!

See the answers in this thread .请参阅此线程中的答案。 You probably need to use one of the third-party big integer libraries/classes available or wait for C# 4.0 which will include a native BigInteger datatype.您可能需要使用可用的第三方大整数库/类之一,或者等待包含本机 BigInteger 数据类型的 C# 4.0。

As far as defining how much memory an app will use, you can check the available memory before performing an operation by using the MemoryFailPoint class.至于定义应用程序将使用多少内存,您可以使用MemoryFailPoint类在执行操作之前检查可用内存。

This allows you to preallocate memory before doing the operation, so you can check if an operation will fail before running it.这允许您在执行操作之前预先分配内存,因此您可以在运行之前检查操作是否会失败。

You don't need to use BigInteger.您不需要使用 BigInteger。 You can do this even with string array of numbers.即使使用数字字符串数组,您也可以做到这一点。

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

I am not sure if it is a good way of handling it, but I use the following in my project.我不确定这是否是处理它的好方法,但我在我的项目中使用了以下内容。

I have a "double theRelevantNumber" variable and an "int PowerOfTen" for each item and in my relevant class I have a "int relevantDecimals" variable.对于每个项目,我有一个“double theRelevantNumber”变量和一个“int PowerOfTen”,在我的相关类中,我有一个“int relatedDecimals”变量。

So... when large numbers is encountered they are handled like this:所以......当遇到大量时,它们的处理方式如下:

First they are changed to x,yyy form.首先将它们更改为 x,yyy 形式。 So if the number 123456,789 was inputed and the "powerOfTen" was 10, it would start like this:因此,如果输入数字 123456,789 并且“powerOfTen”为 10,它将像这样开始:

theRelevantNumber = 123456,789 PowerOfTen = 10 The number was then: 123456,789*10^10 theRelevantNumber = 123456,789 PowerOfTen = 10 当时的数字是:123456,789*10^10

It is then changed to: 1,23456789*10^15然后改为:1,23456789*10^15

It is then rounded by the number of relevant decimals (for example 5) to 1,23456 and then saved along with "PowerOfTen = 15"然后按相关小数位数(例如 5)四舍五入为 1,23456,然后与“PowerOfTen = 15”一起保存

When adding or subracting numbers together, any number outside the relevant decimals are ignored.将数字相加或相减时,相关小数之外的任何数字都将被忽略。 Meaning if you take:意思是如果你采取:

1*10^15 + 1*10^10 it will change to 1,00001 if "relevantDecimals" is 5 but will not change at all if "relevantDecimals" are 4. 1*10^15 + 1*10^10 如果“relevantDecimals”为 5,它将变为 1,00001,但如果“relevantDecimals”为 4,则根本不会改变。

This method make you able to deal with numbers up doubleLimit*10^intLimit without any problem, and at least for OOP it is not that hard to keep track of.这种方法使您能够毫无问题地处理 doubleLimit*10^intLimit 上的数字,并且至少对于 OOP 而言,跟踪起来并不难。

If you want to work with incredibly large numbers look here...如果你想处理非常大的数字,请看这里......

MIKI Calculator 三木计算器

I am not a professional programmer i write for myself, sometimes, so sorry for unprofessional use of c# but the program works.我不是为自己编写的专业程序员,有时,很抱歉不专业地使用 c#,但程序可以工作。 I will be grateful for any advice and correction.我将不胜感激任何建议和纠正。 I use this calculator to generate 32-character passwords from numbers that are around 58 digits long.我使用这个计算器从大约 58 位长的数字中生成 32 个字符的密码。 Since the program adds numbers in the string format, you can perform calculations on numbers with the maximum length of the string variable.由于程序以字符串格式添加数字,因此您可以对字符串变量的最大长度的数字进行计算。 The program uses long lists for the calculation, so it is possible to calculate on larger numbers, possibly 18x the maximum capacity of the list.该程序使用长列表进行计算,因此可以计算更大的数字,可能是列表最大容量的 18 倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM