core.exception.OutOfMemoryError @(0)使用大型动态数组

时间:2015-07-12 23:10:30

标签: arrays d biginteger dynamic-arrays

import std.math;
import std.bigint;
import std.stdio;

BigInt sum_min_pfactor(long N){
    BigInt f(int n) {
        return BigInt(n)*(BigInt(n)+1) / 2 - 1;
    }

    int v = cast(int)(sqrt(float(N)));

    bool[] used;
    used.length = v+1;

    BigInt ret;
    BigInt finish;

    BigInt[] s_sum,s_cnt,l_cnt,l_sum;
    s_sum.length = v+1;
    l_sum.length = v+1;
    s_cnt.length = v+1;
    l_cnt.length = v+1;

    for (long i = 0; i <= v; i++) {
        s_cnt[i] = i - 1;
        s_sum[i] = f(cast(int)i);
    }

    for (long i = 1; i <= v; i++) {
        l_cnt[i] = N / cast(int)i - 1;
        l_sum[i] = f(cast(int)(N) / cast(int)i);
    }

    for (long p = 2; p <= v; p++) {
        if (s_cnt[p] == s_cnt[p-1]) {
            continue;
        }

        BigInt p_cnt = s_cnt[p-1];
        BigInt p_sum = s_sum[p - 1];
        long q = p * p;

        ret = ret + p * (l_cnt[p] - p_cnt);
        l_cnt[1] = l_cnt[1] - l_cnt[p] + p_cnt;
        l_sum[1] = l_sum[1] - (l_sum[p] - p_sum) * p;

        long interval = (p & 1) + 1;

        if (v > N / q) {
            finish = N / q;
        }
        else {
            finish = v; 
        }

        for (long i = p+interval; i <= finish; i += interval){
            if (used[i]) {
                continue;
            }

            long d = i * p;

            if (d <= v) {
                l_cnt[i] = l_cnt[i] - l_cnt[d] + p_cnt;
                l_sum[i] = l_sum[i] - (l_sum[d] - p_sum) * p;
            }
            else {
                long t = N / d;   
                l_cnt[i] = l_cnt[i] - s_cnt[t] + p_cnt;
                l_sum[i] = l_sum[i] - (s_sum[t] - p_sum) * p;
            }
        }

        if (q <= v) {
            for (long i = q; i < finish; i += p*interval){
                used[i] = true;
            }
        }

        for (long i = v; i >= q - 1; i--) {
            long t = i / p;
            s_cnt[i] = s_cnt[i] - s_cnt[t] + p_cnt;
            s_sum[i] = s_sum[i] - (s_sum[t] - p_sum) * p;
        }
    }
    return l_sum[1] + ret;
}

void main () {
    writeln(sum_min_pfactor(pow(10,12)));
}

上面的代码在处理10 ^ 9以下的数字时效果很好。但是,在尝试计算10 ^ 9的答案后,它会开始提供不正确的值并因内存错误而崩溃。我正在使用BigInt库,但我的猜测是未被声明为BigInts的变量之一正在弄乱我的结果。我还假设内存错误是由动态数组的大小引起的,但我无法弄清楚如何解决这个特定的问题。

1 个答案:

答案 0 :(得分:1)

答案是std.math.pow()函数中的静默整数溢出。

的输出
writefln("%d", pow(10, 12));
writefln("%d", pow(10, 12L));

-727379968
1000000000000

现在sqrt(-727379968)-nan。转换为整数给出int.min,约为-2 GiB。数组的length属性是无符号的。因此,每个数组的大小为type.sizeof * 2 GiB,这解释了内存不足错误。

解决方案:将后缀L添加到一个或两个数字,例如

writeln(sum_min_pfactor(pow(10L,9L)));