如何编写解决方案以处理大量数据?

时间:2010-01-02 10:22:00

标签: c types largenumber bignum

我正在做一些Project Euler问题,而且大多数时候,计算涉及的数字超出了int,float,double等。

首先,我知道我应该寻找更有效的计算方法,以避免出现大量问题。 我听说过Bignum图书馆。

但是,对于学术界的兴趣,我想知道如何编写我自己的解决方案来解决这个问题。

任何专家都可以帮帮我吗? (我的语言是C)

7 个答案:

答案 0 :(得分:15)

您需要将大数字存储在计算机可以使用其本机类型轻松处理的基础中,然后将数字存储在可变长度数组中。我建议为简单起见,首先将数字存储在基数10中,以便了解如何执行此操作。它将使调试变得更加容易。

一旦你有一个能够以这种形式存储数字的类,只需要在这个类上实现加,减,乘等操作。每个操作都必须迭代其操作数的数字并组合它们,小心地正确携带,这样你的数字永远不会大于基数。加法和减法很简单。乘法需要更多的工作,因为朴素算法需要嵌套循环。然后,一旦你有了这个工作,你可以尝试以有效的方式实现取幂(例如重复平方)。

如果您打算编写严重的 bignum实现,基数10将不会删除它。它浪费了内存,而且速度很慢。您应该选择一个对计算机来说很自然的基数,例如256或字大小(2 ** 32)。但是这会使简单的操作变得更加困难,因为如果你天真地添加两位数就会出现溢出,所以你需要非常仔细地处理它。

答案 1 :(得分:12)

C对于Project Euler来说不是一个好选择。 C的好处是原始速度,机器可移植性(在某种程度上,使用标准C),语言互操作性(如果某种语言与另一种语言通信,C是一种流行的首选),坚持接近特定的库或平台的API(因为C是常见的,例如OS API),以及稳定的语言和STDLIB。 这些好处都不适用于解决Project Euler问题。甚至没有原始速度,因为大多数问题不是原始计算,而是理解所需的算法,你可以整天坐在那里等待在提交之前。

如果您正在尝试使用Project Euler问题来扩展您使用C的体验,那就完全没问题了,只需要意识到这种体验并不一定适用于您可能工作的长寿和真实C项目上。

对于这种简短的一次性问题,那些通常被称为“脚本语言”的语言将更好,更快(在开发时间),并且更容易。尝试使用Python,它在很多方面都与C保持接近,包括一个C API,并且在各种流行的“脚本语言”中可能会找到与C项目结合使用最多的语言。

这可能会成为一个不受欢迎的答案,但它并不是一个咆哮 - 我真的很喜欢C并经常使用C / C ++ - 并且这里有一个明确的答案:“不要使用C”,您的最终大数解决方案取决于您选择的替代方案。再次选择Python,整数没有上限(请注意下面),我使用它来自然地编写Project Euler问题的答案,在其他语言中我必须使用比较痛苦的替代数字库。

Python整数: 2.x中有两种整数类型,'int'和'long'(已在3.x中完全统一)。它们之间的转换实际上是无缝的,'long'允许任意大的值,而不仅仅是C长的更大的'int'类型。)

答案 2 :(得分:3)

一种简单的方法是将数字视为基数b中的字符串表示形式。假设b = 10,可以使用我们在通过笔和纸添加数字时使用的相同方法,在两个这样的字符串上添加简单的算术运算。其他简单操作也是如此。为了获得更好的结果,您可以采取更大的基础。

这样的简单bignum实现对于大多数Project Euler问题应该足够了(可能全部,但我在Euler上没有解决太多,所以不能确定),但是有一些方法可以使用更快的算法来进行操作作为乘法和除法/ mod。

虽然我建议你自己编写自己的bignum,如果你真的被困住了,你可以从已经实现的bigint库的代码中获取想法。对于一个严肃的实现,像gmp这样的东西是明显的选择。但是,当你在网上解决类似的练习题时,你也可以找到由其他人编写的小bigint(例如Abednego的bigint.cpp)。

答案 3 :(得分:3)

用于C / C ++的流行bignum库是GNU MP Bignum Library。我已经将它用于了几个Project Euler问题,但事实上C仍然不是一个非常适合Euler问题的语言。如果性能更重要的话,C会有更多的东西可以提供,但现在你使用内置bignum支持的语言会更好,例如Ruby(还有很多其他语言)。

答案 4 :(得分:1)

Here's一个漂亮而简单的Cignum模块,你可以从中学到很多想法。 C代码不是最高质量的,但算法实现得很好并且很常见。

有关更高级的内容,请查看GMP。

答案 5 :(得分:0)

如果你想要一个不错的C ++版本(我知道,你说C,但这是非常有趣的代码),请看一下CGAL的内部结构:http://www.cgal.org/

答案 6 :(得分:0)

我完全同意罗杰佩特。我见过许多人遇到过使用C / C ++ / Java的整数限制问题,但是对于Python来说,这是一个非问题。对于大多数项目Euler问题,提出正确的算法是最重要的,而从C获得的性能并不重要。使用Python中可用的关联数据类型,字典,集合等以及一些内置库(itertools),仅举几例,解决Python问题的速度要快得多。我开始认真学习Python,因为我跳过Project Euler的潮流,我对我的决定感到满意(我的第一语言是C ++,第二语言是Perl,但我想学习Python)。