大小为2 ^ 24的Hashtable抛出内存异常,尝试使用Shanks BSGS解决离散日志

时间:2011-09-20 07:25:28

标签: c# hashtable

我正在尝试解决离散日志2 ^ x = r(mod m)。 其中m,2 ^ 47

所以我创建了一个大小为2 ^ 24的哈希表,并使用它来存储一个整数键和一个BigInteger值。

这是我的代码:

using System;
    using System.Collections.Generic;
    using System.Collections;
    using System.Linq;
    using System.Text;
    using System.Numerics;

    namespace Shanks_BSGS_Algorithm
    {
        class Program
        {
            static int Main()
            {
                BigInteger g = 2,temp = 2,n = (Math.Sqrt(281474976710656));
                Hashtable b = new Hashtable(n);
                int i=0;
                b.Add(0, 1);
                i++;
                for (i = 1; (BigInteger)i < n ; i++)
                {
                    temp *= g;
                    b.Add(i,temp);
                }

                return 0;
            }
        }
    }

如果它有所作为。我在具有1.5 GB RAM和32位Windows 7的6年前笔记本电脑上运行Visual C#2010 Express。 提前谢谢。

2 个答案:

答案 0 :(得分:0)

temp变得非常大(高达16777216位)。所以你的hashset包含1600万个非常长的BigIntegers。也许你想减少临时模态,但当g = 2时,这当然会变为0,而m是2的幂。所以你想要做的事情并不是很清楚。

答案 1 :(得分:0)

首先,我认为您需要使用temp值作为数据的关键:

// this makes more sense, otherwise you
// could simply have an array of BigIntegers
b.Add(temp,i);

关于内存问题,.NET不允许任何进程使用超过2Gb的内存,如果需要连续的块,则允许更少的内存。由于你在处理非常大的数字时,内存耗尽是不可避免的。

一种解决方案(首选,如果您只需要最终结果)将使用不同的算法(Pollard's rho algorithm),这样的空间效率更高,运行时间也相似。

如果您真的想测试BSGS算法,您可能需要选择基于磁盘的哈希表。我不知道.NET的任何实现,但你可能会发现几个C ++项目,看看你是否可以轻松移植它们(例如DBH)。

如果你找不到这样的哈希表,比移植更简单的解决方案(好吧,取决于你的数据库技能)可能是使用你习惯的关系数据库,使用一个可以允许足够大的整数的模式。您可以尝试使用SQLite,随着它的增长而变慢,但我相信速度对您来说并不重要。具有一些正确索引的SQL Server可能运行良好。