所以,我的代码无法超越这一行:
double correction = ((double) (1/(1 + pow(2, ((double) ((popsize - maxpop)/maxpop)))))) + 0.5;
popsize
是int
,maxpop
是long 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;
}
答案 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;
这更具可读性,因为括号更少,演员阵容更少。
您是否尝试过在冻结时打印各种值?如果你不确定为什么会出现问题,首先要做的事情就是确保你知道你正在使用什么价值。