Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;无序的记忆_C++_Algorithm_Memory Management_For Loop - Fatal编程技术网

C++ C++;无序的记忆

C++ C++;无序的记忆,c++,algorithm,memory-management,for-loop,C++,Algorithm,Memory Management,For Loop,这个程序通过从1到400的4个数字的每一个组合来查看产品可以生成多少个唯一的数字。 我相信用来保存已经检查过的数字的unordered_set太大了,因此它退出了;任务管理器告诉我它是1.5GB 有没有办法让这段代码运行?我想可能是把集合分开,或者找到一个更有效的公式 注:根据评论,我想再次指出,我并没有存储所有250亿个数字。我只存储了约100000000个数字。这个问题的范围为400,但我正在寻找一个全面的解决方案,可以处理500个,甚至1000个,而不存在内存问题 #include <

这个程序通过从1到400的4个数字的每一个组合来查看产品可以生成多少个唯一的数字。 我相信用来保存已经检查过的数字的
unordered_set
太大了,因此它退出了;任务管理器告诉我它是1.5GB

有没有办法让这段代码运行?我想可能是把集合分开,或者找到一个更有效的公式

注:根据评论,我想再次指出,我并没有存储所有250亿个数字。我只存储了约100000000个数字。这个问题的
范围为400,但我正在寻找一个全面的解决方案,可以处理500个,甚至1000个,而不存在内存问题

#include <iostream>
#include <unordered_set>
using namespace std;

const int RANGE = 400;

int main(){

    unordered_set<long long> nums;

    for(long long a=1; a<=RANGE; a++)
    {
        for(long long b=a; b<=RANGE; b++)
        {
            for(long long c=b; c<=RANGE; c++)
            {
                for(long long d=c; d<=RANGE; d++)
                {
                    unordered_set<long long>::const_iterator got = nums.find(a*b*c*d);
                    if (got == nums.end())
                    {
                        nums.insert(a*b*c*d);
                    }
                }
            }
        }
        cout << a << endl;
    }

    cout << nums.size() << endl;

    return 0;
}
#包括
#包括
使用名称空间std;
常数int范围=400;
int main(){
无序的集合nums;

对于(long long a=1;a,您需要使用64位编译器编译代码,以允许分配超过2GB的内存。在运行此操作的机器上,您还需要至少4GB的RAM,或者最多需要花费几乎永远的时间才能完成

“位集”,每个条目使用一个位,将占用大约3GB的内存

使用现有的代码,它将在带有64位g++编译器的Linux机器上使用大约4GB的内存,完成大约需要220秒,给出了答案:

86102802
1152921504606846975
根据/usr/bin/time-v:

Command being timed: "./a.out"
User time (seconds): 219.15
System time (seconds): 2.01
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 3:42.53
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 4069336
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 679924
Voluntary context switches: 1
Involuntary context switches: 23250
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

您的解决方案是对1到400之间的四个数字进行每个唯一的排列,相乘,存储结果,然后计数。这至少需要400*400*400*400位~3GB,这显然超出了硬件/编译器/操作系统的处理能力。(可能是编译器,它很容易修复)

那么,如果我们试图一步一步地解决这个程序呢?我们能数一数有多少组这些数字的乘积在1000到2000之间吗

for(a=1; a<400; ++a)
{
    bmin = max(1000/a/400/400, a); //a*b*400*400 is at least 1000
    bmax = min(2000/a, 400);       //a*b*1*1 is at most 2000
    for(b=bmin; b<=bmax; b++)
    {
        cmin = max(1000/a/b/400, b);  //a*b*c*400 is at least 1000
        cmax = min(2000/a/b, 400);    //a*b*c*1 is at most 2000
        for(c=cmin; c<=cmax; c++)
        {
            dmin = max(1000/a/b/c, c);   //a*b*c*d is at least 1000
            dmax = min(2000/a/b/c, 400); //a*b*c*d is at most 2000
            for(d=dmin; d<=dmax; d++) //this will usually be zero, one, or two numbers
            {
                res = a*b*c*d;
                if (res>=1000 && res<2000) //a rare few WILL be outside this range
                    YES

当我研究这个问题时,我最终想到的是,我的算法需要大量的64位除法,即使在64位操作系统中,这似乎也很慢。

400^4是25600000000-250亿整数需要相当多的内存来存储,即使消除了重复项。实际上,作为一个位集(每个条目一位),它可以容纳大约3GB的内存。当然,这在32位应用程序或内存远小于4GB的机器中是不会发生的。而且,您可能需要为64位编译代码,以便将超过2GB的代码分配为一个连续的内存块。顺便说一句,您的测试是多余的,它内置在
std::unordered_set::insert
中。我不确定我是否接受你估计的数百万,但这并不重要。数十亿中的数百万只是一个舍入误差。你应该回答@MatsPeterson。我只是在我的机器上编译了这段代码,它需要大约3.5-4GB的ram才能完成(在Linux上使用g++和glibc,其他操作系统、编译器和库可能不同)这就是我所考虑的,但是有没有1-500或1-1000的解决方案?有没有一种方法不让所有数据同时存储在内存中?可能有一些方法,但是当你开始处理大文件时,它也会变得有点复杂,而且通常速度也会非常慢(硬盘的访问时间在毫秒范围内,即使较慢的内存也在100ns范围内。因此硬盘的速度约为1000倍).考虑到它需要相当长的时间,它可能不太可能以1000倍的速度运行良好-即使它偶尔只慢1000倍,它也会产生相当大的影响。想象一下,以1000英里/小时的速度飞行,然后一次步行一英里,每15分钟一次…@qwr我很确定有更好的算法但是,你应该为此提出一个新的问题,因为这与原来的问题没有任何关系。在我的机器上,500的范围,或者与上面相同,占用了大约8GB的RAM。这并不多,但在1000^4时,我们谈论的是更大的数量,所以这可能是不可行的。正如Niklas所说,你我可能想用另一种方法来解决这个问题——我对algo并不总是那么聪明,所以不确定是否有另一种解决方案可以轻易获得。@MatsPetersson:我认为在任意的结果范围内解决这个问题是可能的,(1000)这似乎是可行的,但是
bmin
bmax
cmin
cmax
cmax
dmin
dmax
的意义何在?它们似乎是不必要的,你可以“直接”将程序设置为正确的范围数组?我不确定这将如何实现。@qwr:如果您的目标范围是1000-2000,并且
a=20
b=30
,那么
cmax=2000/20/30=3
。这意味着
c
只测试值1、2和3,而不是一直测试到400。高于3的任何值都将超过max.类似地,如果
a=1
b=1
c=3
,那么
dmin=1000/1/1/3=333
,这意味着你只需要从333-400测试
d
。任何较小的值都不会达到最小值。有可能
bmin
bmax
,或者其他值是多余的,但我并不马上就知道哪个是一个我知道删除
dmin
,或
dmax
会使程序慢得多。“至少需要400*400*400*400位”这不是真的,它需要不同乘积的数量*整数空间的大小。@NiklasB.因为这个数字更大,我的陈述是:不完全是驻留,
86e6*8
(假设8字节整数)小于
400^4/8
。它与大于400的范围更为相关。不过这只是一个小小的吹毛求疵,因为将所有内容都保留在内存中是不明智的
origional(   4) found          25 in      0s
     duck(   4) found          25 in      0s
origional(   6) found          75 in      0s
     duck(   6) found          75 in      0s
origional(   9) found         225 in      0s
     duck(   9) found         225 in      0s
origional(  13) found         770 in      0s
     duck(  13) found         770 in      0s
origional(  17) found        1626 in  0.001s
     duck(  17) found        1626 in      0s
origional(  25) found        5135 in  0.004s
     duck(  25) found        5135 in  0.002s
origional(  35) found       14345 in  0.011s
     duck(  35) found       14345 in  0.015s
origional(  50) found       49076 in  0.042s
     duck(  50) found       49075 in  0.076s
origional(  71) found      168909 in  0.178s
     duck(  71) found      168909 in  0.738s
origional( 100) found      520841 in  0.839s
     duck( 100) found      520840 in  7.206s
origional( 141) found     1889918 in  5.072s
     duck( 141) found     1889918 in 76.028s