繁体   English   中英

超几何分布的C代码优化

[英]Optimization of C code for hypergeometric distribution

我必须优化给定的 C 代码:-

#include<sys/time.h>
#include<stdio.h>
#define GAP(start, end) ((end.tv_usec-start.tv_usec)+(end.tv_sec-start.tv_sec)*1000000)
void main(){
    struct timeval start_time, end_time;
    gettimeofday(&start_time, NULL);
    /* START OF BLOCK */
    long int n, N, e, E, e_choose_i, E_e_choose_N_i, E_choose_N;
    float p_value = 0;
    long int i, var1, var2, var3, var4; // Temporary variables
    fscanf(stdin, "%ld%ld%ld%ld", &n, &N, &e, &E);
    for(i = n; i <= N; i++){
        for(var1 = 1, var4 = 2; var4 <= e; var4++)
            var1 = var1 * var4; // Computes e!
        for(var2 = 1, var4 = 2; var4 <= i; var4++)
            var2 = var2 * var4; // Computes i!
        for(var3 = 1, var4 = 2; var4 <= e-i; var4++)
            var3 = var3 * var4; // Computes (e-i)!
        e_choose_i = var1/(var2*var3); // Computes (e choose i)
        for(var1 = 1, var4 = 2; var4 <= (E-e); var4++)
            var1 = var1 * var4; // Computes (E-e)!
        for(var2 = 1, var4 = 2; var4 <= (N-i); var4++)
            var2 = var2 * var4; // Computes (N-i)!
        for(var3 = 1, var4 = 2; var4 <= ((E-e)-(N-i)); var4++)
            var3 = var3 * var4; // Computes ((E-e)-(N-i))!
        E_e_choose_N_i = var1/(var2*var3); // Computes ((E-e) choose (N-i))
        p_value += e_choose_i*E_e_choose_N_i;
    }
    for(var1 = 1, var4 = 2; var4 <= E; var4++)
        var1 = var1 * var4; // Computes E!
    for(var2 = 1, var4 = 2; var4 <= N; var4++)
        var2 = var2 * var4; // Computes N!
    for(var3 = 1, var4 = 2; var4 <= E-N; var4++)
        var3 = var3 * var4; // Computes (E-N)!
    E_choose_N = var1/(var2*var3); // Computes (E choose N)
    p_value /= E_choose_N;
    /* END OF BLOCK */
    gettimeofday(&end_time, NULL);
    printf("p-value = %f (%d microseconds)", p_value, (int) GAP(start_time, end_time));
}

我使用动态编程方法来找到二项式系数并将代码修改为:-

#include<sys/time.h>
#include<stdio.h>
#define GAP(start, end) ((end.tv_usec-start.tv_usec)+(end.tv_sec-start.tv_sec)*1000000)
void main(){
    struct timeval start_time, end_time;
    gettimeofday(&start_time, NULL);
    /* START OF BLOCK */
    long int n, N, e, E, e_choose_i, E_e_choose_N_i, E_choose_N;
    float p_value = 0;
    long int i; //var1, var2, var3, var4; // Temporary variables
    int p,q,r;
    fscanf(stdin, "%ld%ld%ld%ld", &n, &N, &e, &E);
    for(i = n; i <= N; i++){
        long int C[e+1][i+1];
        for(p=0;p<=e;p++)
        {
            r=(p<i)?p:i;
            for(q=0;q<=r;q++)
            {
                if(q==0 || q==p)
                    C[p][q]=1;
                else
                    C[p][q]=C[p-1][q-1]+C[p-1][q];
            }
        } 
        e_choose_i=C[e][i];
        long int C1[E-e+1][N-i+1];
        for(p=0;p<=E-e;p++)
        {
            r= (p<N-i)?p:N-i ;
            for(q=0;q<=r;q++)
            {
                if(q==0 || q==p)
                    C1[p][q]=1;
                else
                    C1[p][q]=C1[p-1][q-1]+C1[p-1][q];
            }
        } 
        E_e_choose_N_i = C1[E-e][N-i]; // Computes ((E-e) choose (N-i))
        p_value += e_choose_i*E_e_choose_N_i;
       }
     long int C2[E+1][N+1];
        for(p=0;p<=E;p++)
        {
            r= (p<N)?p:N ;
            for(q=0;q<=r;q++)
            {
                if(q==0 || q==p)
                    C2[p][q]=1;
                else
                    C2[p][q]=C2[p-1][q-1]+C2[p-1][q];
            }
        }   
    E_choose_N = C2[E][N]; // Computes (E choose N)
    p_value /= E_choose_N;
    /* END OF BLOCK */
    gettimeofday(&end_time, NULL);
    printf("p-value = %f (%d microseconds)", p_value, (int) GAP(start_time, end_time));
}

较小的值例如 n=2,N=3,e=3 和 E=7 花费的时间更少,但对于较大的值(例如 n=3,N=8,e=10 和 E=15)花费更多的时间. 如何针对大值对其进行优化。 请帮忙。

正如dmuir所指出的

您将 fscanf 包含在您的定时序列中。 这将花费大部分时间。 对 function 的多次调用而不是一次调用计时总是一个好主意。

除此之外,您可以尝试不同的方法来评估二项式系数:

double binomial(long n, long k)
{
    double result = 1.0;
    if ( k > n/2 )
        k = n - k;
    ++n;
    for (int i = 1; i <= k; ++i)
        result *= (double)(n - i) / i;
    return result;
}

这样计算(如果我得到正确的话)减少到

for(int i = n; i <= N; i++)
{       
    p_value += binomial(e, i) * binomial(E - e, N - i);
}
p_value /= binomial(E, N);

在这里测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM