The task was to implement an algorithm for solving a given system of nonlinear equations by the Newton method. The essence of the algorithm in the cyclic calculation of floating-point numbers. When I started testing the program on different devices for the sake of interest, I got a strange result. To obtain the final result, different devices require a different number of cycles, despite the same input data and result. Here is what the devices showed (invariably at each launch):
- Meizu M2 Note (MT6753 8 * 1.3Ghz Cortex A53, 64bit): 229 cycles;
- ASUS Zenfon 5 (Intel Atom Z2560 2 * 1.6Ghz x86): 145 cycles;
- Lenovo A850 + (MT6592): 149 cycles;
- Samsung Galaxy A3 (Qualcomm Snapdragon 410 4 * 1.2Ghz Cortex A53 64bit): 1878 cycles.
I also noticed that the number of cycles for all devices with qualcomm snapdragon is the same: 1878. Algorithm code:
ArrayList<Box> box = new ArrayList<Box>(); MyAdapter adapter; ListView listView; double precision = 1E-28; double K1F1, K2F1, K3F1, K4F1, K1F2, K2F2, K3F2, K4F2, K1F3, K2F3, K3F3; int flag=0; //ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π²ΡΡΠ°ΡΠΈΠ» ΠΈΠ· ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΠΊΠ½ΠΎΠΏΠΊΠΈ, ΠΎΠ½ ΡΠ°ΠΌ Π½Π΅ Π²Π°ΠΆΠ΅Π½. Π ΡΡΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π² countFx() ΠΈ countWx() K1F1=16d; K2F1=16d; K3F1=1d; K4F1=16d; K1F2=1d; K2F2=1d; K3F2=1d; K4F2=3d; K1F3=1d; K2F3=1d; K3F3=0d; private double[] Countfx(double[] x){//Π²Π΅ΠΊΡΠΎΡ Fx double[] fx = new double[3]; fx[0] = K1F1*Math.pow(x[0],4)+K2F1*Math.pow(x[1],4)+K3F1*Math.pow(x[2],4)-K4F1; fx[1] = K1F2*Math.pow(x[0],2)+K2F2*Math.pow(x[1],2)+K3F2*Math.pow(x[2],2)-K4F2; fx[2] = K1F3*Math.pow(x[0],3)-K2F3*x[1]-K3F3; return fx; } private double Countdet(double[][] ar){//ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ ΠΌΠ°ΡΡΠΈΡΡ 3*3 double detar; detar = ar[0][0]*ar[1][1]*ar[2][2] + ar[0][1]*ar[1][2]*ar[2][0] + ar[0][2]*ar[1][0]*ar[2][1] - ar[2][0]*ar[1][1]*ar[0][2] - ar[2][1]*ar[1][2]*ar[0][0] - ar[2][2]*ar[1][0]*ar[0][1]; return detar; } private double[][] CountWx(double[] x){//ΠΌΠ°ΡΡΠΈΡΠ° ΡΠΊΠΎΠ±ΠΈ double[][] Wx = new double[3][3]; Wx[0][0] = K1F1*4d*Math.pow(x[0],3); Wx[1][0] = K2F1*4d*Math.pow(x[1],3); Wx[2][0] = K3F1*4d*Math.pow(x[2],3); Wx[0][1] = K1F2*2d*x[0]; Wx[1][1] = K2F2*2d*x[1]; Wx[2][1] = K3F2*2d*x[2]; Wx[0][2] = K1F3*3d*Math.pow(x[0],2); Wx[1][2] = K2F3*x[1]; Wx[2][2] = 0; return Wx; } private double[][] CountMinorMatrix(double[][] matrix){//ΠΌΠ°ΡΡΠΈΡΠ° ΠΌΠΈΠ½ΠΎΡΠΎΠ² (Π΄Π»Ρ Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΡ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ) double[][] minor = new double[3][3]; minor[0][0] = matrix[1][1]*matrix[2][2]-(matrix[1][2]*matrix[2][1]); minor[1][0] = matrix[0][1]*matrix[2][2]-(matrix[0][2]*matrix[2][1]); minor[2][0] = matrix[0][1]*matrix[1][2]-(matrix[1][1]*matrix[0][2]); minor[0][1] = matrix[1][0]*matrix[2][2]-(matrix[1][2]*matrix[2][0]); minor[1][1] = matrix[0][0]*matrix[2][2]-(matrix[0][2]*matrix[2][0]); minor[2][1] = matrix[0][0]*matrix[1][2]-(matrix[1][0]*matrix[0][2]); minor[0][2] = matrix[1][0]*matrix[2][1]-(matrix[1][1]*matrix[2][0]); minor[1][2] = matrix[0][0]*matrix[2][1]-(matrix[0][1]*matrix[2][0]); minor[2][2] = matrix[0][0]*matrix[1][1]-(matrix[0][1]*matrix[1][0]); return minor; } private double[][] getTransposedMatrix(double[][] matrix){//ΡΡΠ°Π½ΡΠΏΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠ°ΡΡΠΈΡΡ double[][] tr = new double[3][3]; for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ tr[i][j]=matrix[j][i]; } } return tr; } private double[][] MultiplyMatrixAtNumber(double[][] m, double num){//ΡΠΌΠ½ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠ°ΡΡΠΈΡΡ 3*3 Π½Π° ΡΠΈΡΠ»ΠΎ for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ m[i][j]*=num; } } return m; } private double[][] getInverseMatrix(double[][] m){//Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ double det = Countdet(m); m=CountMinorMatrix(m); if(m[1][0]>0) m[1][0]=-Math.abs(m[1][0]); else m[1][0]=Math.abs(m[1][0]); if(m[0][1]>0) m[0][1]=-Math.abs(m[0][1]); else m[0][1]=Math.abs(m[0][1]); if(m[2][1]>0) m[2][1]=-Math.abs(m[2][1]); else m[2][1]=Math.abs(m[2][1]); if(m[1][2]>0) m[1][2]=-Math.abs(m[1][2]); else m[1][2]=Math.abs(m[1][2]); m=getTransposedMatrix(m); det = 1d/det; m=MultiplyMatrixAtNumber(m,det); return m; } private double[] MultiplyMatrix(double[][] m1, double[] m2){//ΡΠΌΠ½ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠ°ΡΡΠΈΡΡ 3*3 ΠΈ Π²Π΅ΠΊΡΠΎΡΠ° 1*3 double[] res = new double[3]; for(int i=0; i<3; i++) res[i]=0; for(int j=0; j<3; j++){ for(int i=0; i<3; i++){ res[j]+=m1[i][j]*m2[i]; } } return res; } private double[] CountDifMatrix(double[] m1, double[] m2){//ΡΠ°Π·Π½ΠΎΡΡΡ ΠΌΠ°ΡΡΠΈΡ double[] sum = new double[3]; for(int i=0; i<3; i++){ sum[i] = m1[i]-m2[i]; } return sum; } private boolean compare(double[] m1, double[] m2){//ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ Π²Π΅ΠΊΡΠΎΡΠΎΠ² int n=0; for(int i=0; i<3; i++){ if(m1[i]==m2[i]) n++; } if(n>=2) return true; else return false; } private void CountFunction(){ double[] X0={1d,1d,1d}; double[] Fx; double[][] Wx; double det; double[][] WxInverse; double[] multRes; double[] result; int w=0, it=0, col=0; while(w==0 && col<1){ Fx=Countfx(X0);//Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ Π²Π΅ΠΊΡΠΎΡΠ° Fx Wx=CountWx(X0);//Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΌΠ°ΡΡΠΈΡΡ ΡΠΊΠΎΠ±ΠΈ det=Countdet(Wx);//Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ ΠΌΠ°ΡΡΠΈΡΡ Π΄Π»Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ Π½Π° 0 if(det==0){ break; } WxInverse=getInverseMatrix(Wx);//Π½Π°Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ multRes=MultiplyMatrix(WxInverse,Fx); result=CountDifMatrix(X0,multRes); Box b=new Box(result);//ΠΎΠ±ΡΠ΅ΠΊΡ ΠΏΡΠΎΡΡΠΎ Ρ
ΡΠ°Π½ΠΈΡ ΠΌΠ°ΡΡΠΈΠ² (Π΄Π»Ρ ArrayList Π½ΡΠΆΠ΅Π½ Π°Π±ΡΡΡΠ°ΠΊΡΠ½ΡΠΉ ΡΠΈΠΏ) outputNumbersinLog(result);//Π»ΠΎΠ³ box.add(b);// Π·Π°ΠΏΠΈΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ° ΡΠΈΠΊΠ»Π° Π² arraylist boolean compare=compare(X0,result);//ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ° ΡΠ΅ΠΊΡΡΠ΅Π³ΠΎ ΠΈ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π³ΠΎ ΡΠΈΠΊΠ»ΠΎΠ² if(compare) col++; for(int i=0; i<3; i++){ if(Math.abs(result[i])<precision){ w=1; } } X0=result;//ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΡΠΈΠΊΠ»Π° ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ Π²Ρ
ΠΎΠ΄Π½ΡΠΌ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠΌ Π΄Π»Ρ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ it++; } Log.d("function","ΠΡΠ΅ΡΠ°ΡΠΈΠΉ: "+it); Box out = box.get(it-1); //Π²ΡΠ²ΠΎΠ΄ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ° Π² TextView ((TextView)findViewById(R.id.X)).setText("X = "+out.s[0]); ((TextView)findViewById(R.id.Y)).setText("Y = "+out.s[1]); ((TextView)findViewById(R.id.Z)).setText("Z = "+out.s[2]); }
strictfp
class / methods with thestrictfp
modifier. - zRrr 2:26 pm