Help me to find max value in looping

Hi guys, i am currently working on jacobi transformation program. my program is supposed to find max value of 2 dimension matrix and transformed it using sin & cos matrix transformation. it will produce new matix with new max value on it. the process is repeated again until all non-diagonal element close to zero.

i wrote my program like this (u can skip to read the whole progam. i ask my queation in the end of this post ) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#include <iostream>
#include <algorithm>
#include <cmath>
#include <iterator>
#include <ctime>
#include <iomanip>
#define phi 3.14
#define tol 0.001

using namespace std;

int const dimensi = 3;
double matrik[dimensi][dimensi]= {{12,6,-6},{6,16,2},{-6,2,16}};
double k, jacobi[dimensi][dimensi], jacobi_baru[dimensi][dimensi],data[dimensi][dimensi],rotasi[dimensi][dimensi],rotasi_in[dimensi][dimensi];
double maks;
double nilai,nilai_abs,bar,kol,teta,sudut,s,c,t,penyebut,delta,coteta;
int main ()
{
for (int k=0;k<3;k++)
{
maks = 0;
cout <<endl<< "matriks : " << endl;
// matriks
	for (int i =0;i<dimensi;i++)
     {
        for (int j=0;j<dimensi;j++)
        {
        cout << matrik[i][j] << "  ";
        }
        cout << endl;
     }
cout << endl;
	
//finding max value
	for (int i=0;i<dimensi;i++)
	{
		for (int j=0;j<dimensi;j++)
		{	
		if (i!=j)
		{
			nilai_abs = sqrt (matrik[i][j]*matrik[i][j] ) ;
			cout << "index= " << i<< "," <<j<<" value : " << nilai_abs; 
			if (nilai_abs > maks)
			{
				maks = matrik[i][j];
			}		
			else {
				maks=maks;
			}
			cout << " maks value: " << maks<<endl; 
		}
		}
	}
	
	nilai = maks;
	cout <<" max value: " << nilai<<endl<<endl;
	
	
	for (int a=0;a<dimensi;a++)
	{
		for (int b=0;b<dimensi;b++)
		{	
			if ( matrik[a][b] == nilai)
			{
				bar =a;
				kol = b;
			}
		}
	}
 
//jacobi transformation
int a=bar,b=kol;
cout << bar << " and " << kol << endl;		
cout << matrik[a][b] <<endl<<endl;

	penyebut = matrik[a][a]-matrik[b][b];
        delta = penyebut/(2.0*(matrik[b][a]));

		if (delta >= 0 )
		{
			t = 1 / ( delta + sqrt( (delta*delta) +1 ) );
				}		
		else
		{
			t = 1 / ( delta + sqrt( (delta*delta) +1 ) );
		}
		
		c = 1 / ( sqrt( 1 + (t*t) ) );
		s = c*t;
		
		cout << " delta = " << delta << " angle value= " << sudut << endl;
		cout << " nilai t= " << t << " sin= " << s << " cos= " <<c<< endl;
		
			rotasi[b][b] = c;
            rotasi[a][a] = c;
            rotasi[b][a] = s;
            rotasi[a][b] = -s;
		
			rotasi_in[b][b] = c;
            rotasi_in[a][a] = c;
            rotasi_in[b][a] = -s;
            rotasi_in[a][b] = s;
			
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
        if(i==j)
        {
        	if(i!=a && i!=b)
        	{
        		rotasi[i][j] = 1; 
			}
        	
		}
    }
    }

for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
        if(i==j)
        {
        	if(i!=a && i!=b)
        	{
        		rotasi_in[i][j] = 1; 
			}
        	
		}
    }
    }

cout << "Matrik rotasi: " << endl;
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
		cout << fixed;
        cout << setprecision(2) << rotasi[i][j] << setw(4) << "    ";
    }
    cout << endl;
    }

cout << endl<<endl<<"Matrik rotasi inverse: " << endl;
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
		cout << fixed;
        cout << setprecision(2) << rotasi_in[i][j] << setw(4) << "    ";
    }
    cout << endl;
    }


cout<<endl << "jacobi : " << endl;
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
    	for (int k=0;k<dimensi;k++)
		{ 
        jacobi[i][j] += rotasi_in[i][k]*matrik[k][j];
    	}
		cout <<fixed;
        cout << setprecision(2) << jacobi[i][j] << setw(4) << "    ";
    }
    cout << endl;
    }

//print out jacobi
cout<<endl << " new jacobi : " << endl;
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
    for (int k=0;k<dimensi;k++)
		{ 
	    jacobi_baru[i][j] += jacobi[i][k]*rotasi[k][j];
		}
        cout <<fixed;
        cout << setprecision(2) << jacobi_baru[i][j] << setw(4) << "    ";
    }
    cout << endl;
    }

//change the old matrix with new jacobi's matrix
cout<<endl << "data diagonalnya adalah: " << endl;
for (int i=0;i<dimensi;i++)
    {
for (int j=0;j<dimensi;j++)
    {
	    data[i][j] = jacobi_baru[i][j];
	cout << fixed;
    cout << setprecision(2) << data[i][j] << setw(4) << "    ";
	matrik [i][j] = data[i][j];
	}
    cout << endl;
    }    
}

}


in the first loop it works as it supposed to be. but the problem appear in the second loops when i try to find max value of matrix.


1. in the first loops :
matrix : 12 6 -6
6 16 2
-6 2 16

max value of each element ()
index : 0,1 value(in abs form) : 6 maks value :6
index : 0,2 value : 6 maks value :6
index : 1,0 value : 6 maks value :6
index : 1,2 value : 2 maks value :6
index : 2,0 value : 6 maks value :6
index : 2,1 value : 2 maks value :6

max value = 6


2.in the second loops :
matrix : 7.68 0 -6.04
0 20.32 -1.89
-6.04 -1.89 16.00

max value of each element :
index : 0,1 value : 0.00 maks value :-0.00
index : 0,2 value : 6.04 maks value :-6.04
index : 1,0 value : 0.00 maks value :-0.00
index : 1,2 value : 1.89 maks value :-1.89
index : 2,0 value : 6.04 maks value :-6.04
index : 2,1 value : 1.89 maks value :-1.89

max value = -1.89


on the second looping, the max value indicate the last value (not a max value anymore) in looping.
i dont understand, It work well in the first process but not in the second looping and so on.
Is there something i have missed?

Thanks,

P.S : i am pretty sure my problem not in the jocobi trans method. but in the finding max value in looping matrix.
Last edited on
if ( matrik[a][b] == nilai)

Equality comparison for doubles doesn't work, their representation is not exact.

One can write a function that determines "equality" within a certain precision. See if the absolute value of the difference between the numbers is less than the precision value.

Good Luck !!
try to avoid using #define , declare constexpr variables instead. Try not to declare more than one variable per line.

Also, don't have global variables.

I am not a fan of i and j for variables names for matrices, they are too similar - that can cause hard to see problems.

Thanks for your advice TheIdeasMan.

i wrote this code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
#include <iostream>

using namespace std;

double a[8]={2.31,2.3,2.00,2.32,2.31,2.30,2,2.315};
double b=2.31;
int c=2;

int main()
{
    for (int x=0;x<8;x++)
    {	
		if (b==a[x]) 	
		{
			cout << " b equal to a " <<endl;
			}	
		else
		{
			cout << " b  not equal to a " <<endl;
		}
		
	}
}


The result is
1
2
3
4
5
6
7
8
b equal to a
b  not equal to a
b  not equal to a
b  not equal to a
b  equal to a
b  not equal to a
b  not equal to a
b  not equal to a


i am not sure that i understand, what do you mean by
Equality comparison for doubles doesn't work, their representation is not exact.
and why do i need a function that determines "equality" within a certain precision ?

in my previous code, in the line 45 i wrote
maks = matrik[i][j];

in line 55 i wrote
nilai = maks;

in line 63 i wrote
if ( matrik[a][b] == nilai)


so i thought its precision doesnt change.

i also 2nd case (the simpler one, that add randoms value to each matrix element instead of using jacobi trnsformation) that use the same principle as the 1st one. which is finding the max value of non-diagonal element of matrix and repeated with x times looping. each value of that matrix is changed each time its looping.

the code is :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <algorithm>
#include <iterator>
#include <ctime>
#include <cmath>
#include <iomanip>

using namespace std;

int const dimensi = 3;
double matrik[dimensi][dimensi]= {{12,6,-6},{6,16,2},{-6,2,16}};
double  jacobi_baru[dimensi][dimensi];
double data[dimensi][dimensi];
double maks;
double nilai,nilai_abs,bar,kol;

int main ()
{

for (int k=0;k<3;k++)
{
srand(time (0));

maks = 0;
cout <<endl<< "matrix : " << endl;

//matrix
	for (int row=0;row<dimensi;row++)
     {
        for (int col=0;col<dimensi;col++)
        {
        cout << matrik[row][col] << "  ";
        }
        cout << endl;
     }
cout << endl;
	
	
//finding max value
	for (int row=0;row<dimensi;row++)
	{
		for (int col=0;col<dimensi;col++)
		{	
		if (row!=col)
		{
			nilai_abs = sqrt (matrik[row][col]*matrik[row][col] ) ;
			cout << "indexs " << row<< "," <<col<<" abs value : " << nilai_abs; 
			if (nilai_abs > maks)
			{
				maks = matrik[row][col];
			}		
			else {
				maks=maks;
			}
			cout << " max value: " << maks<<endl; 
		}
		}
	}
	
	nilai = maks;
	cout <<" nilai maksimum: " << nilai<<endl<<endl;
	
//finding the index of max value
	for (int a=0;a<dimensi;a++)
	{
		for (int b=0;b<dimensi;b++)
		{	
			if ( matrik[a][b] == nilai)
			{
				bar =a;
				kol = b;
			}
		}
	}
	
int a=bar,b=kol;
cout << "indexs of max value" << bar << "," << kol << endl;		
cout << matrik[a][b] <<endl<<endl;

for (int row=0;row<dimensi;row++)
    {
for (int col=0;col<dimensi;col++)
    {
	jacobi_baru[row][col] = matrik [row][col] + rand() %20;
	cout << fixed;
    cout << setprecision(2) << jacobi_baru[row][col] << setw(4) << "    ";
	}
    cout << endl;
    }    

cout<<endl << "data diagonalnya adalah: " << endl;
for (int row=0;row<dimensi;row++)
    {
for (int col=0;col<dimensi;col++)
    {
	    data[row][col] = jacobi_baru[row][col];
	cout << fixed;
    cout << setprecision(2) << data[row][col] << setw(4) << "    ";
	matrik [row][col] = data[row][col];
	}
    cout << endl;
    }    
}

}


and it works perfectly.
so my conclusion is i have done something wrong on my previous code, but dont know where yet.
Last edited on
Please restructure your code to make it easier to read:
- use consistent indentation
- don't introduce lots of unnecessary variables (especially matrices)
- your max calculations was wrong; matrix elements weren't zeroed before collecting the multiply

It would help other forum users if you posted a link to define your transformation.

See the comments in a modified version of your first code below.
It seems to produce the eigenvalues as the diagonals after a few passes.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <iostream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <iomanip>
                                    // <===== remove unnecessary headers
using namespace std;

int main ()
{
   // <===== Moved inside main(); don't use unnecessary global variables
   const int passmax = 10;          // <===== need a maximum number of iterations
   const double tol = 0.001;        // <===== better here (pi not needed)
   int const dimensi = 3;
   double matrik[dimensi][dimensi]= {{12,6,-6},{6,16,2},{-6,2,16}};
   double jacobi[dimensi][dimensi],
          rotasi[dimensi][dimensi],rotasi_in[dimensi][dimensi];
   double maks;
   double nilai_abs,s,c,t,delta;     // <==== remove unnecessary variables
   int a, b;      // <==== need a and b in scope
   int pass = 0;  // <==== need to count iterations

   while ( pass < passmax )       // <==== need some maximum number of iterations
   {
      // Matrix at start of loop
      maks = 0;
      cout <<endl<< "matriks : " << endl;
      for (int i =0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            cout << matrik[i][j] << "  ";
         }
         cout << endl;
      }
      cout << endl;
        
      // Finding max value (off diagonal)         // <=====
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {       
            if (i!=j)
            {
               nilai_abs = abs (matrik[i][j]);    // <===== much more sense than sqrt() version
               if (nilai_abs > maks)
               {
                  maks = nilai_abs;
                  a = i;
                  b = j;                          // <===== combine into this loop
               }                                  // <===== simplify; bar and kol not needed
//             else
//             {                                  //
//                maks=maks;                      // <===== utterly pointless
//             }                                  //
            }
         }
      }
 
      // Jacobi transformation
      cout << "a = " << a << ";   b = " << b << endl;
      cout << "matrik[a][b] = " << matrik[a][b] <<endl<<endl;

      if ( maks < tol ) break;                    // <====== MUST have an exit criterion

      delta = (matrik[b][b]-matrik[a][a])/(2.0*matrik[a][b]);   // <===== correct and simplify
      if (delta >= 0 )
      {
         t = 1 / ( delta + sqrt( delta*delta +1 ) );
      }
      else
      {
         t = -1 / ( -delta + sqrt( delta*delta +1 ) );   // <===== correct this
      }
                
      c = 1 / ( sqrt( 1 +  t*t  ) );
      s = c*t;
                
      cout << " delta = " << delta << endl;
      cout << " nilai tan= " << t << " sin= " << s << " cos= " <<c<< endl;

      // <===== set default (identity) matrix first; THEN change the Jacobi components
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            rotasi[i][j] = 0;
         }
         rotasi[i][i] = 1;    // <==== override diagonal element
      }

      // <===== now insert the rotation matrix elements
      rotasi[a][a] = c;
      rotasi[b][b] = c;
      rotasi[a][b] = s;       // <==== correct this
      rotasi[b][a] = -s;
                
      // <==== Set up transpose (inverse for orthogonal matrices)
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            rotasi_in[i][j] = rotasi[j][i];
         }
      }

      cout << "Rotation matrix: " << endl;
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            cout << fixed << setprecision(2) << rotasi[i][j] << setw(4) << "    ";
         }
         cout << endl;
      }

      // <===== Premultiply by transpose (inverse)
      cout<<endl << "PT * M: " << endl;
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            jacobi[i][j] = 0.0;                    // <==== must initialise element as zero
            for (int k=0;k<dimensi;k++)
            { 
               jacobi[i][j] += rotasi_in[i][k]*matrik[k][j];
            }
            cout <<fixed << setprecision(2) << jacobi[i][j] << setw(4) << "    ";
         }
         cout << endl;
      }

      // Postmultiply by rotation matrix
      cout<<endl << "PT * M * P: " << endl;
      for (int i=0;i<dimensi;i++)
      {
         for (int j=0;j<dimensi;j++)
         {
            matrik[i][j] = 0.0;                    // <==== must initialise element as zero
            for (int k=0;k<dimensi;k++)
            { 
               matrik[i][j] += jacobi[i][k]*rotasi[k][j];   // <===== Jacobi_baru not needed
            }
            cout <<fixed << setprecision(2) << matrik[i][j] << setw(4) << "    ";
         }
         cout << endl;
      }
      cout << "\n========== END OF PASS =======\n";
      pass++;
   }
}

and why do i need a function that determines "equality" within a certain precision ?


There are lots of real numbers which are not represented exactly - they are basically stored as binary fractions.

1
2
3
double a = 0.1; // 0.099999999999997 say, could be 0.1 + 2e-15
double b = 10.0 * a; // 0.99999999999997
if (b == 1.0) // false 


There are some numbers which can be represented exactly, so equality comparison works for these, but it is not reliable for all the numbers.

In your code which "tests" the equality of the doubles, both variables are initialised with the same prvalue (in this case a literal value)2.31 so they will be the same. But when one starts doing calculations, then expect a certain exact value (hence an equality), that is when it all goes wrong.

With binary fractions:

0.1binary = 0.5decimal 1.0/ 2.01
0.01b = 0.25d 1.0/2.02
0.001b = 0.125d 1.0/2.03

So 3.0/8.0 is 0.011b and that is exact.

Now imagine the binary fraction can only have a limited significant figures. So, one can see how there will be some numbers that don't quite work out exactly, but others do.
Last edited on
Thanks lastchance and TheIdeasMan all of it help me a lot. thanks
Topic archived. No new replies allowed.