C# 在 .NET 中处理非常大的数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/279038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:19:49  来源:igfitidea点击:

working with incredibly large numbers in .NET

c#.netbigintegerlargenumber

提问by Greg B

I'm trying to work through the problems on projecteuler.netbut 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>. I keep getting OutOfMemoryException's when storing large quantities in the list.

第一个是将大量元素存储在List<t>. 在列表中存储大量数据时,我不断收到 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 数据类型,我认为数字会变得非常大,但我仍然设法绕过支持的最大整数并进入负数。

Do you have any tips for working with incredibly large numbers?

你有什么处理难以置信的大数字的技巧吗?

采纳答案by Larsenal

回答by ine

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 libraryon CodePoject seems to be the most promising. The article has some good explanations of how operations with massive numbers work, as well.

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

Also see: Big integers in C#

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

回答by Scott Dorman

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。

回答by MrKurt

I assume this is C#? F# has built in ways of handling both these problems (BigInt type and lazy sequences).

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

You can use both F# techniques from C#, if you like. The BigInt type is reasonably usable from other languages if you add a reference to the core F# assembly.

如果愿意,您可以使用 C# 中的两种 F# 技术。如果添加对核心 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. 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!

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

回答by Jake Pearson

As far as Project Euler goes, you might be barking up the wrong tree if you are hitting OutOfMemory exceptions. From their website:

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

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.

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

回答by Cameron MacFarland

As far as defining how much memory an app will use, you can check the available memory before performing an operation by using the MemoryFailPointclass.

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

This allows you to preallocate memory before doing the operation, so you can check if an operation will fail before running it.

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

回答by abelenky

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. Its more about finding the proper algorithm to avoid big-numbers.

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

Want hints? Post here, and we might have an interesting Euler-thread started.

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

回答by Abhilash Virat

You don't need to use BigInteger You can do this event with string array of numbers.

您不需要使用 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;
    }
}

回答by Milod Orif

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

回答by Allan Karseth

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. So if the number 123456,789 was inputed and the "powerOfTen" was 10, it would start like this:

首先将它们更改为 x,yyy 形式。因此,如果输入数字 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 来说,跟踪起来并不难。