c++ - Keeping accuracy when taking decimal to power of integer -
my code follows (i have simplified ease of reading, sorry lack of functions):
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <iomanip> #include <fstream> #include <time.h> #include <stdlib.h> #include <sstream> #include <gmpxx.h> using namespace std; #define pi 3.14159265358979323846 int main() { int a,b,c,d,f,i,j,k,m,n,s,t,success,fails; double p,theta,phi,time,averagetime,energy,energy,distance,length,dotprodforce, forcemagnitude,forcemagnitude[201],force[201][4],e[1000001],en[501],epsilon[4],ep, x[201][4],new_x[201][4],y[201][4],a[201],alpha[201][201],degree,bestalpha[501]; clock_t t1,t2; t1=clock(); t=1; /* set parameter t, power in energy function */ while(t<1001){ n=2; /*set parameter n, number of points going onto sphere */ while(n<51){ cout << "n=" << n << "\n"; b=0; time=0.0; /* set parameter b, loop distribute points many times (100) */ while(b<100){ clock_t t3,t4; t3=clock(); if(n>200){ cout << n << " many points me :-( \n"; exit(0); } srand((unsigned)time(0)); (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } /* points have been distributed randomly , normalised sit on unit sphere */ energy=0.0; for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); energy=energy+1.0/pow(distance,t); } } /*energy has been calculated system of points summation function accuracy lost */ for(i=1;i<=n;i++){ y[i][1]=x[i][1]; y[i][2]=x[i][2]; y[i][3]=x[i][3]; } m=100; if (m>100){ cout << "the m="<< m << " loop inefficient...lessen m \n"; exit(0); } a=1; /* distributing points m-1 times , choosing best random distribution */ while(a<m){ (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } energy=0.0; for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); energy=energy+1.0/pow(distance,t); } } if(energy<energy) for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ energy=energy; y[i][j]=x[i][j]; } } else for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ energy=energy; x[i][j]=y[i][j]; } } a=a+1; } /* end of random distribution loop, loop a<m */ en[b]=energy; b=b+1; t4=clock(); float diff ((float)t4-(float)t3); float seconds = diff / clocks_per_sec; time = time + seconds; } /* end of looping entire body of program, used average reading */ t2=clock(); float diff ((float)t2-(float)t1); float seconds = diff / clocks_per_sec; n=n+1; } /* end of n loop, here n increases outputs n 2 50 each t */ if(t==1) t=2; else if(t==2) t=5; else if(t==5) t=10; else if(t==10) t=25; else if(t==25) t=50; else if(t==50) t=100; else if(t==100) t=250; else if(t==250) t=500; else if(t==500) t=1000; else t=t+1; } /* end of t loop, t changes decided values estimate tammes's problem t large possible t>200 makes energy calculations lose accuracy */ return 0; } /* end of main function , therefore program. in original seen following link below code use gradient flow algorithm before end of b, n , t loops minimise energy function , therefore accurate solutions. */
every time run code t>200 energy output loses accuracy (as raised high power), have been told need use arbitrary precision integers , gmp library. have done , have managed code run gmp library in scope, don't supposed alter.
do alter t or energy (and energy) or distance or 3 (/four)?? don't understand supposed change, reading how manual.
note:my original question here, thought had been answered , warranted new one. shall accept answer there when works: losing accuracy large integers (pow?)
i have altered code (shown below), coming segmentation fault 11 initialise en[b]. appreciate if comments little more in-depth do. far, a.
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <iomanip> #include <fstream> #include <time.h> #include <stdlib.h> #include <sstream> #include <gmpxx.h> using namespace std; #define pi 3.14159265358979323846 int main() { int a,b,c,d,f,i,j,k,m,n,s,success,fails; double p,theta,phi,time,averagetime,distance,length,dotprodforce, forcemagnitude,forcemagnitude[201],force[201][4],e[1000001],epsilon[4],ep, x[201][4],new_x[201][4],y[201][4],a[201],alpha[201][201],degree,bestalpha[501]; unsigned long int t; mpf_t energy,energy,power,d,en[501]; mpf_set_default_prec(1024); mpf_init(power); mpf_init(d); clock_t t1,t2; t1=clock(); t=1000; /* set parameter t, power in energy function */ while(t<1001){ n=2; /*set parameter n, number of points going onto sphere */ while(n<51){ cout << "n=" << n << "\n"; b=0; time=0.0; /* set parameter b, loop distribute points many times (100) */ while(b<101){ clock_t t3,t4; t3=clock(); if(n>200){ cout << n << " many points me :-( \n"; exit(0); } srand((unsigned)time(0)); (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ cout << "x[" << << "][" << j << "]=" << x[i][j] << "\n"; } } /* points distributed randomly , normalised sit on unit sphere */ mpf_init (energy); for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); mpf_set_d(d,distance); mpf_pow_ui(power,d,t); mpf_ui_div(power,1.0,power); mpf_add(energy,energy,power); } } cout << "energy=" << energy << "\n"; /*energy calculated summation function accuracy lost */ for(i=1;i<=n;i++){ y[i][1]=x[i][1]; y[i][2]=x[i][2]; y[i][3]=x[i][3]; } m=100; if (m>100){ cout << "the m="<< m << " loop inefficient...lessen m \n"; exit(0); } a=1; /* distributing points m-1 times , choosing best random distribution */ while(a<m){ (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ cout << "x[" << << "][" << j << "]=" << x[i][j] << "\n"; } } mpf_init(energy); for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); mpf_set_d(d,distance); mpf_pow_ui(power,d,t); mpf_ui_div(power,1.0,power); mpf_add(energy,energy,power); } } cout << "energy=" << energy << "\n"; if(energy<energy) for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ mpf_set(energy,energy); y[i][j]=x[i][j]; } } else for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ mpf_set(energy,energy); x[i][j]=y[i][j]; } } a=a+1; } /* end of random distribution loop, loop a<m */ cout << "energy=" << energy << "\n"; mpf_init(en[b]); mpf_set(en[b],energy); for(i=0;i<=b;i++){ cout << "en[" << << "]=" << en[i] << "\n"; } b=b+1; t4=clock(); float diff ((float)t4-(float)t3); float seconds = diff / clocks_per_sec; time = time + seconds; } /* end of looping entire body of program, used average reading */ t2=clock(); float diff ((float)t2-(float)t1); float seconds = diff / clocks_per_sec; n=n+1; } /* end of n loop, here n increases outputs n 2 50 each t */ if(t==1) t=2; else if(t==2) t=5; else if(t==5) t=10; else if(t==10) t=25; else if(t==25) t=50; else if(t==50) t=100; else if(t==100) t=250; else if(t==250) t=500; else if(t==500) t=1000; else t=1001; } /* end of t loop, t changes decided values estimate tammes's problem t large possible t>200 makes energy calculations lose accuracy */ return 0; } /* end of main function , therefore program. in original seen following link below code use gradient flow algorithm before end of b, n , t loops minimise energy function , therefore accurate solutions. */
the code looks this, in future apparently must learn how use gmp library can found here http://gmplib.org, issue have had solved helpful people in comments, check them out if having issues. thanks.
#include <stdio.h> #include <string.h> #include <math.h> #include <iostream> #include <iomanip> #include <fstream> #include <time.h> #include <stdlib.h> #include <sstream> #include <gmpxx.h> using namespace std; #define pi 3.14159265358979323846 int main() { int a,b,c,d,f,i,j,k,m,n,s,success,fails; double p,theta,phi,time,averagetime,distance,length,dotprodforce, forcemagnitude,forcemagnitude[201],force[201][4],e[1000001],epsilon[4],ep, x[201][4],new_x[201][4],y[201][4],a[201],alpha[201][201],degree,bestalpha[501]; unsigned long int t; mpf_t energy,energy,power,d,en[501]; mpf_set_default_prec(1024); mpf_init(power); mpf_init(d); clock_t t1,t2; t1=clock(); t=1000; /* set parameter t, power in energy function */ while(t<1001){ n=2; /*set parameter n, number of points going onto sphere */ while(n<3){ cout << "n=" << n << "\n"; b=0; time=0.0; /* set parameter b, loop distribute points many times (100) */ while(b<2){ clock_t t3,t4; t3=clock(); if(n>200){ cout << n << " many points me :-( \n"; exit(0); } srand((unsigned)time(0)); (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ cout << "x[" << << "][" << j << "]=" << x[i][j] << "\n"; } } /* points distributed randomly , normalised sit on unit sphere */ mpf_init (energy); for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); mpf_set_d(d,distance); mpf_pow_ui(power,d,t); mpf_ui_div(power,1.0,power); mpf_add(energy,energy,power); } } cout << "energy=" << energy << "\n"; /*energy calculated summation function accuracy lost */ for(i=1;i<=n;i++){ y[i][1]=x[i][1]; y[i][2]=x[i][2]; y[i][3]=x[i][3]; } m=100; if (m>100){ cout << "the m="<< m << " loop inefficient...lessen m \n"; exit(0); } a=1; /* distributing points m-1 times , choosing best random distribution */ while(a<m){ (i=1;i<=n;i++){ x[i][1]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][2]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; x[i][3]=((rand()*1.0)/(1.0*rand_max)-0.5)*2.0; length=sqrt(pow(x[i][1],2)+pow(x[i][2],2)+pow(x[i][3],2)); (k=1;k<=3;k++){ x[i][k]=x[i][k]/length; } } for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ cout << "x[" << << "][" << j << "]=" << x[i][j] << "\n"; } } mpf_init(energy); for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); mpf_set_d(d,distance); mpf_pow_ui(power,d,t); mpf_ui_div(power,1.0,power); mpf_add(energy,energy,power); } } cout << "energy=" << energy << "\n"; if(energy<energy) for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ mpf_set(energy,energy); y[i][j]=x[i][j]; } } else for(i=1;i<=n;i++){ for(j=1;j<=3;j++){ mpf_set(energy,energy); x[i][j]=y[i][j]; } } a=a+1; } /* end of random distribution loop, loop a<m */ cout << "energy=" << energy << "\n"; mpf_init(en[b]); mpf_set(en[b],energy); for(i=0;i<=b;i++){ cout << "en[" << << "]=" << en[i] << "\n"; } for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ distance=sqrt(pow(x[i][1]-x[j][1],2)+pow(x[i][2]-x[j][2],2) +pow(x[i][3]-x[j][3],2)); degree=(180/pi); alpha[i][j]=degree*acos((2.0-pow(distance,2))/2.0); } } for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ cout << "alpha[" << << "][" << j << "]=" << alpha[i][j] << "\n"; } } for(i=1;i<=n-1;i++){ for(j=i+1;j<=n-1;j++){ if(alpha[i][j]>alpha[i][j+1]) alpha[i][j]=alpha[i][j+1]; else alpha[i][j+1]=alpha[i][j]; } } for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ cout << "alpha[" << << "][" << j << "]=" << alpha[i][j] << "\n"; } } for(i=1;i<=n-2;i++){ if(alpha[i][n]>alpha[i+1][n]) alpha[i][n]=alpha[i+1][n]; else alpha[i+1][n]=alpha[i][n]; } for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ cout << "alpha[" << << "][" << j << "]=" << alpha[i][j] << "\n"; } } bestalpha[b]=alpha[n-1][n]; for(i=1;i<=b;i++){ cout << "best angle[" << << "]: " << bestalpha[b] << "\n"; } b=b+1; t4=clock(); float diff ((float)t4-(float)t3); float seconds = diff / clocks_per_sec; time = time + seconds; } /* end of looping entire body of program, used average reading */ t2=clock(); float diff ((float)t2-(float)t1); float seconds = diff / clocks_per_sec; n=n+1; } /* end of n loop, here n increases outputs n 2 50 each t */ if(t==1) t=2; else if(t==2) t=5; else if(t==5) t=10; else if(t==10) t=25; else if(t==25) t=50; else if(t==50) t=100; else if(t==100) t=250; else if(t==250) t=500; else if(t==500) t=1000; else t=1001; } /* end of t loop, t changes decided values estimate tammes's problem t large possible t>200 makes energy calculations lose accuracy */ return 0; } /* end of main function , therefore program. in original seen following link below code use gradient flow algorithm before end of b, n , t loops minimise energy function , therefore accurate solutions. */
Comments
Post a Comment