pow应该能够处理这样的事情:为什么我的代码在此时冻结了?

时间:2012-10-08 00:28:28

标签: c double pow

所以,我的代码无法超越这一行:

double correction = ((double) (1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5;

popsizeintmaxpoplong int,由用户定义,并且分别限制在1到10,000和1到500,000之间的值(尽管我将来可能会对maxpop设置更高的限制,这就是提前long int的原因。我意识到大多数double都是多余的,但我想保持肯定。代码编译时没有任何警告,但一旦实际到达正在运行,它就会挂起。我尝试在声明之后直接打印correction,但是因为它被卡在那条线上而没有跑。另外,不要担心,我没有忘记包含math.h(虽然我最初做过,并且在另外的隐式声明错误时遇到了同样的问题)。出了什么问题?

编辑:这是我的所有代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

long double randomDouble() {
    long double r = (long double)rand()/(long double)RAND_MAX;
    return r;
}

int tryBernoulli(long double p) {
    if ((long double)rand()/(long double)RAND_MAX < p) {
        return 1;
    } else
        return 0;
}

int tryRademacher() {
    if (rand() % 2) {
        return 1;
    }
    return -1;
}

int calculateSeries(int arg) {
    int sum = 0;
    for (int i = 0; i <= arg; i++) {
        sum = sum + i;
    }
    return sum;
}

int main() {
    long double allp [1001] [33];
    long double p [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int allalsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int alsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int nalsum [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    long double selection [33] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int allgenotypes [467];
    for (int i = 0; i <= 465; i++) {
        allgenotypes[i] = 0;
    }
    int genotypes [467];
    for (int i = 0; i <= 465; i++) {
        genotypes[i] = 0;
    }
    int a,b; // The two alleles generated during generation for a single organism.
    int temp; // A temporary variable to store numbers in.
    long double randdbl = 0; // The number that randomDouble generates.
    int randint = 0; // A random integer (for safekeeping).
    int alnum = 2;
    int popsize = 1;
    int npopsize = 0;
    long int maxpop = 0;
    int gens = 1;
    long double fsum = 0; // For keeping track of what part of the probability distro you're in.
    int isum = 0; // For keeping track of what part of the gene pool you're in.
    int input = 0;
    long double finput = 0;
    long int linput = 0;
    printf("Hello! Welcome to Mike's Glorious Evolutionary Modeler. This models the genetic drift of a single gene in a population of arbitrary size. For a sufficiently large population, you should get no drift at all! To start, specify the starting population size (from 1 to 10,000, no commas please):\n");
    scanf("%d",&input);
    if (input < 1 || input > 10000) {
        while (input < 1 || input > 10000) {
            printf("That was outside of the limits (1 to 10,000)! Try again:\n");
            scanf("%d",&input);
        }
    }
    popsize = input;
    printf("\nAnd give the environmental population cap (between 1 and 500,000):\n");
    scanf("%ld",&linput);
    if (input < 1 || linput > 500000) {
        while (input < 1 || linput > 500000) {
            printf("That was outside of the limits (1 to 500,000)! Try again:\n");
            scanf("%ld",&linput);
        }
    }
    maxpop = linput;
    printf("\nNext, tell me how many alleles you would like (between 2 and 32):\n");
    scanf("%d", &input);
    if (input < 2 || input > 32) {
        while (input < 2 || input > 32) {
            printf("That was outside of the limits (2 to 32)! Try again:\n");
            scanf("%d",&input);
        }
    }
    alnum = input;
    printf("\nTime to specify the probabilities of all of the alleles (except the last one)! Specify each, up to four decimal places. They have to add up to 1. ");
    for (int i = 1; i <= (alnum-1); i++) {
        printf("Please enter the probability of Allele %d, denoted A%d (between 0 and %Lf, inclusive):\n", i, i, (1-fsum));
        scanf("%Lf",&finput);
        if (fsum + finput > 1) {
            while (fsum + finput > 1) {
                printf("That put the sum over 1! Try again:\n");
                scanf("%Lf",&finput);
            }
        }
        p[i-1] = finput;
        fsum = fsum + finput;
        printf("Now please enter the selection coefficient for Allele %d. If you want the population growth to remain at 0, set it to 1. In order to maintain a reasonable growth rate, this coefficient may be no more than 1.1.\n", i);
        scanf("%Lf",&finput);
        if (finput < 0 || finput > 1.1) {
            while (finput < 0 || finput > 1.1) {
                printf("Nice try. It should be between 0 and 1.1.\n");
                scanf("%Lf",&finput);
            }
        }
        selection[i-1] = finput;
    }
    fsum = 0;
    for (int i = 1; i <= (alnum-1); i++) {
        fsum = fsum + p[i-1];
    }
    p[alnum-1] = 1 - fsum;
    printf("Okay, the probability for A%d will be %Lf. What should its selection coefficient be?\n",alnum,p[alnum-1]);
    scanf("%Lf",&finput);
    if (finput <= 0 || finput > 1.1) {
        while (finput <= 0 || finput > 1.1) {
            printf("Nice try. It should be between 0 and 1.1.\n");
            scanf("%Lf",&finput);
        }
    }
    selection[alnum-1] = finput;
    printf("\nOkay! Enter the amount of generations that the calculations should be done for (between 1 and 1,000):\n");
    scanf("%d",&input);
    if (input < 1 || input > 1000) {
        while (input < 1 || input > 1000) {
            printf("That was outside of the limits (1 to 1,000)! Try again:\n");
            scanf("%d",&input);
        }
    }
    gens = input;
    printf("Okay! Ready to go. Give me a moment...\n\n");
    srand((unsigned int) time(NULL)); // Seed the generator. Only do this once!
    for (int j = 0; j <= popsize-1; j++) { // This part generates and files the alleles and genotypes of the first generation.
        randdbl = randomDouble();
        fsum = 0;
        for (int k = 0; k <= alnum-1; k++) {
            if (randdbl > fsum && randdbl < fsum + p[k]) {
                a = k+1;
                break;
            }
            fsum = fsum + p[k];
        }
        randdbl = randomDouble();
        fsum = 0;
        for (int k = 0; k <= alnum-1; k++) {
            if (randdbl > fsum && randdbl < fsum + p[k]) {
                b = k+1;
                break;
            }
            fsum = fsum + p[k];
        }
        if (a > b) {
            temp = a;
            a = b;
            b = temp;
        }
        allalsum[a-1]++;
        allalsum[b-1]++;
        alsum[a-1]++;
        alsum[b-1]++;
        if (b == a) {
            if (b == 1) {
                genotypes[0]++;
            } else {
                genotypes[calculateSeries(b)-b]++;
                allgenotypes[calculateSeries(b)-b]++;
            }
        } else {
            genotypes[calculateSeries(b-1)+a]++;
            allgenotypes[calculateSeries(b-1)+a]++;
        }
    }
    printf("\nStatistics for Generation 1:\n Population: %d\n Number of Genotype:\n", popsize);
    int index = 0;
    for (int i = 0; i <= alnum-1; i++) {
        printf("  A%dA%d: %d\n",(i+1),(i+1),genotypes[index]);
        index++;
        for (int j = 1; j <= i; j++) {
            printf("  A%dA%d: %d\n",j,(i+1),genotypes[index]);
            index++;
        }
    }
    printf("\n Number of Allele:\n");
    for (int i = 0; i <= alnum-1; i++) {
        printf("  A%d: %d\n",(i+1),alsum[i]);
    }
    printf("\n Percent Allele Composition:\n");
    for (int i = 0; i <= alnum-1; i++) {
        allp [gens] [i] = p[i]; // Store old probability values in array
        p[i] = ((long double) alsum[i])/((long double) (2*popsize)); // Generate new ones from current generation
        printf("  A%d: %Lf%%\n",(i+1),(p[i]*100));
    }
    // Clean up:
    for (int j = 0; j <= 465; j++) {
        genotypes[j] = 0;
    }
    /********************************************************************************************************
     ************************************************IMPORTANT***********************************************
     ********************************************************************************************************/
    for (int i = 2; i <= gens; i++) { // This part calculates the values for all the rest of the generations.
        double correction = ((double) (1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5; // The logistic function that curves the population growth with respect to the population cap.
        for (int j = 0; j <= (alnum-1); j++) {
            for (int k = 0; k <= alsum[j]; k++) {
                while (tryBernoulli(((0.5+correction)*selection[j]))) {
                    nalsum[j]++;
                }
            }
        }
        popsize = 0;
        for (int j = 0; j <= (alnum-1); j++) {
            popsize = popsize+nalsum[j];
        }
        if ((popsize % 2) == 1) {
            popsize--;
            nalsum[rand()%alnum]--;
        }
        for (int j = 0; j <= (alnum-1); j++) {
            alsum[j] = nalsum[j];
            allalsum[j] = allalsum[j] + nalsum[j];
        }
        if (popsize == 0) {
            printf("\nOops! Your population has died out!");
            break;
        }
        npopsize = popsize/2;
        while (npopsize != 0) {
            isum = alsum[0];
            randint = rand()%popsize;
            for (int j = 0; j <= (alnum-1); j++) {
                if (nalsum[j] > 0) {
                    if (randint <= isum) {
                        a = j + 1;
                        nalsum[j]--;
                        break;
                    }
                }
                isum = isum + alsum [j+1];
            }
            isum = alsum[0];
            randint = rand()%popsize;
            for (int j = 0; j <= (alnum-1); j++) {
                if (nalsum[j] > 0) {
                    if (randint <= isum) {
                        b = j + 1;
                        nalsum[j]--;
                        break;
                    }
                }
                isum = isum + alsum [j+1];
            }
            if (b == a) {
                if (b == 1) {
                    genotypes[0]++;
                } else {
                    genotypes[calculateSeries(b)-b]++;
                    allgenotypes[calculateSeries(b)-b]++;
                }
            } else {
                genotypes[calculateSeries(b-1)+a]++;
                allgenotypes[calculateSeries(b-1)+a]++;
            }
            npopsize--;
        }
        popsize = popsize/2;
        printf("\nStatistics for Generation %d:\n Population: %d\n Number of Genotype:\n",i,popsize);
        int index = 0;
        for (int j = 0; j <= alnum-1; j++) {
            printf("  A%dA%d: %d\n",(j+1),(j+1),genotypes[index]);
            index++;
            for (int k = 1; k <= j; k++) {
                printf("  A%dA%d: %d\n",k,(j+1),genotypes[index]);
                index++;
            }
        }
        printf("\n Number of Allele:\n");
        for (int j = 0; j <= alnum-1; j++) {
            printf("  A%d: %d\n",(j+1),alsum[j]);
        }
        printf("\n Percent Allele Composition:\n");
        for (int j = 0; j <= alnum-1; j++) {
            /*allp [gens] [j] = p[j]; // Store old probability values in array */
            p[j] = ((long double) alsum[j])/((long double) (2*popsize)); // Generate new ones from current generation
            printf("  A%d: %Lf%%\n",(j+1),(p[j]*100));
        }
        // Clean up:
        for (int j = 0; j <= 465; j++) {
            genotypes[j] = 0;
        }
        for (int j = 0; j <= 31; j++) {
            nalsum[j] = 0;
        }
    }
    /*printf("\nGraph of Total Amounts of Each Genotype (one # represents 10):\n");
    int index = 0;
    for (int i = 0; i <= alnum-1; i++) {
        printf("  A%dA%d: ",(i+1),(i+1));
        for (int j = 0; j < (allgenotypes[index]/10); j++) {
            printf("#");
        }
        printf("\n");
        index++;
        for (int j = 1; j <= i; j++) {
            printf("  A%dA%d: ",j,(i+1));
            for (int k = 0; k <= (allgenotypes[index]/10); k++) {
                printf("#");
            }
            printf("\n");
            index++;
        }
    }*/
    return 0;
}

2 个答案:

答案 0 :(得分:2)

立即执行:

#include <stdio.h>
#include <math.h>

int
main (int argc, char *argv[])
{

  double popsize = 50;
  double maxpop = 100;
  double correction =
    ((double)(1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5;
  printf ("correction= %f\n", correction);
  return 0;
}

我编译并链接如下(CentOS Linux 5.5,GCC 4.1.2):

gcc -Wall -pedantic tmp.c -o tmp -lm

这是时代(眨眼):

 time ./tmp
correction= 1.085786

real    0m0.002s
user    0m0.000s
sys     0m0.001s
问:你的操作系统和编译器是什么?

问:您是否需要在平台上明确链接数学库(“-lm”)?

答案 1 :(得分:2)

表达式:

((popsize - maxpop)/maxpop)
只要maxpop大于popsize

就会为零。如果你对分数幂感兴趣,你需要更快地转换为双倍。

值为零不应该导致冻结。你有<math.h>吗? (是的:你在这个问题中也说得很多。)如果没有,那你就会遇到更多问题;第一个参数应该是一个明确的双重。

你明智地写道:

double correction = 1.0 / (1.0 + pow(2.0, ((double)popsize - maxpop)/maxpop)) + 0.5;

这更具可读性,因为括号更少,演员阵容更少。

您是否尝试过在冻结时打印各种值?如果你不确定为什么会出现问题,首先要做的事情就是确保你知道你正在使用什么价值。