I am writing an algorithm to do Gaussian elimination. I do not know why the elements of the matrix do not change after the calculations. I think I might need to defined the elements in a different way, but I do not know how. Is there any other easy way to fix this problem?
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n, i, j, k;
float mult;
cout << "Enter the number of equations\n";
cin >> n;
int a[n][n], x[n], b[n];
for (i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
cout << "A[" << i+1 << "][" << j+1 << "]=";
cin >> a[i][j];
}
}
for (i = 0; i<n; i++)
{
cout << "b[" << i+1 << "] is ";
cin >> a[i][n];
}
for (j = 0; j< n; j++)
for (i=j+1; i< n ; i++)
mult = a[i][j] / a[j][j];
for (k = j+1; k < n ; k++)
a[i][k] = a[i][k] - mult * a[j][k];
x[n-1] = a[n-1][n]/ a[n-1][n-1];
for (i = n-2; i=0; i--)
for (j=n-1; j = i+1; j--)
a[i][n] = a[i][n] - a[i][j]*x[j];
x[i] = a[i][n] / a[i][i];
}
I see several problems with your code:
VLAs1 are not standard c++
In standard c++ int a[n][n], x[n], b[n]; is not valid, because n is not constant at compile time. Even if some compilers allow this, don't use it. Use std::vector instead.
The last line of code is not part of any loop
You should use an IDE or simple Editor to fix intendation for you, then you would see, that the last line x[i] = a[i][n] / a[i][i]; is not part of any loop. My tip: always use parantheses after for!
The last loops have a wrong condition
The condition of the last loop for(i = n-2; i=0; i--) is i=0. This will_assign_ the value 0 to i then evaluate i as condition and since i is zero it will exit the loop. Probably you meant to use == to compare the values.
The same thing goes for the nested loop for (j=n-1; j = i+1; j--).2
1Variable Length Arrays
2 Actually this loop will run forever for any n != 0
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm not brilliant at coding, I'm just starting off and the code I created runs with that many errors I feel like I should just start again, but I have no clue what to do differently.
Below is the code I'm running that's coming back with all the errors, I just can't put my finger on what I'm doing wrong and it's so overwhelming.
Please help if you can, thank you x
Edit: sorry I forgot to add the errors! I've got 23 errors, most are 'array type is not assignable' and 'expression did not evaluate to a constant'
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int i, j, k, n, N;
cout.precision(4); //set precision
cout.setf(ios::fixed);
cout << "\nEnter the no. of data pairs to be entered:\n"; //To find the size of arrays that will store x,y, and z values
cin >> N;
double x[N], y[N];
cout << "\nEnter the x-axis values:\n"; //Input x-values
for (i = 0; i < N; i++)
cin >> x[i];
cout << "\nEnter the y-axis values:\n"; //Input y-values
for (i = 0; i < N; i++)
cin >> y[i];
cout << "\nWhat degree of Polynomial do you want to use for the fit?\n";
cin >> n; // n is the degree of Polynomial
double X[2 * n + 1]; //Array that will store the values of sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
for (i = 0; i < 2 * n + 1; i++)
{
X[i] = 0;
for (j = 0; j < N; j++)
X[i] = X[i] + pow(x[j], i); //consecutive positions of the array will store N,sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
}
double B[n + 1][n + 2], a[n + 1]; //B is the Normal matrix(augmented) that will store the equations, 'a' is for value of the final coefficients
for (i = 0; i <= n; i++)
for (j = 0; j <= n; j++)
B[i][j] = X[i + j]; //Build the Normal matrix by storing the corresponding coefficients at the right positions except the last column of the matrix
double Y[n + 1]; //Array to store the values of sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)
for (i = 0; i < n + 1; i++)
{
Y[i] = 0;
for (j = 0; j < N; j++)
Y[i] = Y[i] + pow(x[j], i) * y[j]; //consecutive positions will store sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^n*yi)
}
for (i = 0; i <= n; i++)
B[i][n + 1] = Y[i]; //load the values of Y as the last column of B(Normal Matrix but augmented)
n = n + 1; //n is made n+1 because the Gaussian Elimination part below was for n equations, but here n is the degree of polynomial and for n degree we get n+1 equations
cout << "\nThe Normal(Augmented Matrix) is as follows:\n";
for (i = 0; i < n; i++) //print the Normal-augmented matrix
{
for (j = 0; j <= n; j++)
cout << B[i][j] << setw(16);
cout << "\n";
}
for (i = 0; i < n; i++) //From now Gaussian Elimination starts(can be ignored) to solve the set of linear equations (Pivotisation)
for (k = i + 1; k < n; k++)
if (B[i][i] < B[k][i])
for (j = 0; j <= n; j++)
{
double temp = B[i][j];
B[i][j] = B[k][j];
B[k][j] = temp;
}
for (i = 0; i < n - 1; i++) //loop to perform the gauss elimination
for (k = i + 1; k < n; k++)
{
double t = B[k][i] / B[i][i];
for (j = 0; j <= n; j++)
B[k][j] = B[k][j] - t * B[i][j]; //make the elements below the pivot elements equal to zero or elimnate the variables
}
for (i = n - 1; i >= 0; i--) //back-substitution
{ //x is an array whose values correspond to the values of x,y,z..
a[i] = B[i][n]; //make the variable to be calculated equal to the rhs of the last equation
for (j = 0; j < n; j++)
if (j != i) //then subtract all the lhs values except the coefficient of the variable whose value is being calculated
a[i] = a[i] - B[i][j] * a[j];
a[i] = a[i] / B[i][i]; //now finally divide the rhs by the coefficient of the variable to be calculated
}
cout << "\nThe values of the coefficients are as follows:\n";
for (i = 0; i < n; i++)
cout << "x^" << i << "=" << a[i] << endl; // Print the values of x^0,x^1,x^2,x^3,....
cout << "\nHence the fitted Polynomial is given by:\ny=";
for (i = 0; i < n; i++)
cout << " + (" << a[i] << ")" << "x^" << i;
cout << "\n";
return 0;
}
You have in your code several variables which are declared as double x[N], where N is a variable that is known only at run-time. This is not guaranteed to be supported. Instead, you should use a std::vector, initialized like this: std::vector<double> x(N). This creates a vector of doubles of size N, zero-initialized. Look up how to use vectors here: https://en.cppreference.com/w/cpp/container/vector . Also, you should use descriptive variable names, which will help you read and understand your own code (and others you're asking for help). Don't be afraid of 23 error messages, I routinely get 100+ on first compilation of a fresh batch of code. Often they can cascade where one causes a lot of others down the line, so work starting from the one that's earliest in the code, recompiling after every bugfix. The 100+ effectively become 30 or so, sometimes.
Also, it would be helpful to split your function into several functions, and test each one individually, then bring them all together.
I'm writing Jacobi iterative method to solve any linear system of equations. this program works for some examples but doesn't work for others. for example for
A= and B=
7 3 5
2 3 4
this will works and answers are true but for
A= and B=
1 2 3
3 4 7
the answers are wrong and huge numbers.
I really don't know what should I do to make a correct calculation.
I used some other codes but still I have this issue with codes.
#include <iostream>
using namespace std;
int main(){
double A[10][10], alpha[10][10], B[10], betha[10], x[10][100], sum[10];
int i, j, n, k, kmax;
cout << "insert number of equations \n";
cin >> n;
cout << "insert LHS of equations (a11,a12,...,ann)\n";
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
cin >> A[i][j];
}
}
cout << "A=\n";
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
cout << A[i][j] << "\t\t";
}
cout << "\n\n";
}
cout << "alpha=\n";
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
if (i == j){
alpha[i][j] = 0;
}
else{
alpha[i][j] = -A[i][j] / A[i][i];
}
}
}
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
cout << alpha[i][j] << "\t\t";
}
cout << "\n\n";
}
cout << "insert RHS of equations";
for (i = 1; i <= n; i++){
cin >> B[i];
}
cout << "\nbetha=\n";
for (i = 1; i <= n; i++){
betha[i] = B[i] / A[i][i];
cout << betha[i] << endl;
}
cout << "Enter the number of repetitions." << endl;
cin >> kmax;
k = 0;
for (i = 1; i <= n; i++){
sum[i] = 0;
x[i][k] = betha[i]; //initial values
}
for (k = 0; k <= kmax; k++){
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
sum[i] += alpha[i][j] * x[j][k];
}
x[i][k] = betha[i] + sum[i];
sum[i] = 0;
}
}
cout << "answers:\n\n";
for (i = 1; i <= n; i++){
cout << x[i][kmax] << endl;
}
return 0;
}
You should again check the condition for convergence. There you will find that usually the method only converges for diagonally dominant matrices. The first example satisfies that condition, while the second violates it clearly.
If convergence is not guaranteed, divergence might happen, as you found.
More specifically, the Jacobi iteration in the second example computes
xnew[0] = (3 - 2*x[1])/1;
xnew[1] = (7 - 3*x[0])/4;
Over two iterations the composition of steps gives
xtwo[0] = (3 - 2*xnew[1])/1 = -0.5 + 1.5*x[0];
xtwo[1] = (7 - 3*xnew[0])/4 = -0.5 + 1.5*x[1];
which is clearly expanding the initial errors with factor 1.5.
Your matrix, in row order, is: [{1, 2} {3, 4}]
It has determinant equal to -2; clearly it's not singular.
It has inverse: [{4, -2}, {-3, 1}]/(-2)
The correct solution is: {1, 1}
You can verify this by substituting back into the original equation and checking to make sure you have an identity: [{1, 2} {3, 4}]{1, 1} = {3, 7}
Iterative methods can be sensitive to initial conditions.
The point about diagonally dominant is correct. Perhaps a more judicious choice of initial condition, closer to the right answer, would allow you to converge.
Update:
Jacobi iteration decomposes the matrix into diagonal elements D and off-diagonal elements R:
Jacobi will converge if:
Since this is not the case for the first row of your sample matrix, you might have a problem.
You still get there in a single step if you use the correct answer as your initial guess. This says that even Jacobi will work with a judicious choice.
If I start with {1, 1} I converge to the correct answer in a single iteration.
i dont know whats wrong with my code but im getting same value of "sum" on the
screen..
assume that m and n are entered equal ....enter image description here
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
int n,m;
int *ptr1, *ptr2, *sum;
cout<<" enter the size of 1st and 2nd array : "<<endl;
cin>>n>>m;
ptr1=(int*)malloc(n*sizeof(int));
ptr2=(int*)malloc(m*sizeof(int));
sum=(int*)malloc((n)*sizeof(int));
cout<<"enter 1st array element :";
for(int i=0;i<n;i++)
{
cin>>*(ptr1+i) ;
}
cout<<"enter 2st array element :";
for(int i=0;i<m;i++)
{
cin>>*(ptr2+i);
}
for(int j=0;j<m||j<n;j++)
{
*(sum+j) = (*(ptr1) + *(ptr2)) ;
}
cout<<" the sum is "<<endl;
for(int j=0;j<m||j<n;j++)
{
cout<<*(sum+j)<<endl;
}
}
First, the reason you get the same number springs from where you form the sums.
In this loop
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = (*(ptr1)+*(ptr2));
}
you find the sum of the contents of ptr1 and ptr2 over and over which never change - this is always the first two numbers.
So, we could iterate over the arrays by indexing in j along as follows
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = (*(ptr1 + j) + *(ptr2 + j));
}
BUT what happens if m!=n? You'll walk off the end of the array.
If you change the loop to
for (int j = 0; j<m && j<n; j++)
{
*(sum + j) = (*(ptr1 + j) + *(ptr2 + j));
}
then you find the sum for pairs of numbers up to the smaller of m and n.
You will have to do likewise with the display of the results
for (int j = 0; j<m && j<n; j++)
{
cout << *(sum + j) << endl;
}
However, I believe you wanted to either display n numbers, regardless of which is bigger, or perhaps assume a 0 if there is no element. Also, I notice you have malloced and not freed - perhaps using a C++ array rather than C-style arrays is better? I'll come to that in a moment.
Let's do the C appraoch and have a 0 if we go beyond the end of an array.
This will work, but can be tidied up - comments inline about some important things
#include<stdlib.h>
#include <algorithm> //for std::max
#include <iostream>
using namespace std;
int main()
{
int n, m;
int *ptr1, *ptr2, *sum;
cout << " enter the size of 1st and 2nd array : " << endl;
cin >> n >> m;
ptr1 = (int*)malloc(n * sizeof(int));
ptr2 = (int*)malloc(m * sizeof(int));
sum = (int*)malloc((std::max(n, m)) * sizeof(int));
// ^--- sum big enough for biggest "array"
// data entry as before - omitted for brevity
for (int j = 0; j<m || j<n; j++)
{
*(sum + j) = 0;
if (j < n)
*(sum + j) += *(ptr1 + j);
if (j < m)
*(sum + j) += *(ptr2 + j);
}
cout << " the sum is " << endl;
for (int j = 0; std::max(n, m); j++)//however big it is
{
cout << *(sum + j) << endl;
}
free(ptr1); //tidy up
free(ptr2);
free(sum);
}
I know you said you wanted to use malloc and perhaps this is a practise with pointers, but consider using C++ idioms (at least you won't forget to free things you have maoolced this way).
Let's nudge your code towards using a std::vector:
First the include and the input:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, m;
vector<int> data1, data2, sum;
cout << " enter the size of 1st and 2nd array : " << endl;
cin >> n >> m;
cout << "enter 1st array element :";
for (int i = 0; i<n; i++)
{
int number;
cin >> number;
data1.push_back(number); //there is a neater way, but start simple
}
cout << "enter 2st array element :";
for (int i = 0; i<m; i++)
{
int number;
cin >> number;
data2.push_back(number);
}
This post shows a way to neaten up the data entry. However, let's do something simple and get the sum:
for (int j = 0; j < std::max(m, n); j++)
{
int number = 0;
if (j < n)
number += data1[j];
if (j < m)
number += data2[j];
sum.push_back(number);
}
And now for a C++ way to do output
cout << " the sum is " << endl;
for (auto item : sum)
{
cout << item << '\n';
}
}
Finally, let's have a brief think about the sum.
If you now #include <iterator> you can use an algorithm to put your sum into sum
std::transform(data1.begin(), data1.end(),
data2.begin(), std::back_inserter(sum), std::plus<int>());
However, note this won't fill with zeros. You could either make the vectors the same size, filled with zeros first, or lookup/discover ways to zip vectors of different sizes. Or stick with ifs in a loop as I demonstrated above.
Avoid malloc in C++. Just saying.
I highly encourage you to use a modern cpp data structure like a vector for storing your data. Thus, you don't have to worry about malloc and can access them far more easyly.
But now to your question: Your summation for loop is broken. Use
for(int j=0;j<m||j<n;j++)
{
*(sum+j) = (*(ptr1+j) + *(ptr2+j)) ;
}
Best regrads, Georg
I'm learning C++ and this is one of my first programs that is going to sort a list of numbers, I found the algorithm in Kenneth H. Rosen book and wrote it in C++. when I check it on the paper it seems to be correct, but in practice it has some error. For example I enter 3(enter)2(enter)1(enter)4(enter)5(enter) and it returns 3 1 1 4 5 as the answer. I don't know what is the problem, please help.
int main()
{
int i, j, s, n, k, a[50];
cout << "Enter number of numbers:\n";
cin >> n;
cout << "Enter the numbers:\n";
for (i = 0; i < n; i++) {
cin >> a[i];
}
for (j = 2; j < n; j++) {
i = 1;
while (a[j] > a[i]) {
i = i + 1; // Here we find the proper place to(if needed) directly insert our number into the sorted part.
}
s = a[j];
for (k = 0; k < j - i - 1; k++) {
a[j - k] = a[j - k - 1];
}
a[i] = s;
}
for (i = 0; i < n; i++) {
cout << a[i] << " ";
}
_getch();
return 0;
}
I've also included the header files and namespace, not written here though. And in the case you think I have used so many variables, sorry about that, I needed them :)
Your index i should start from the first element which is 0 instead of 1.
Fixing line 11 should do the job:
for (j = 2; j < n; j++) {
i = 0;
while (a[j] > a[i]) {
Edit:
Oh, and also, your variable j should start from the second element which is index 1 instead of 2:
for (j = 1; j < n; j++) {
So I have an assignment for my C++ class. Basically we have to create a 3x3 multidimensional array, calculate the sum of rows, sum of columns, sum of diagonal values and sum of anti-diagonal values, I usually just input 1 2 3 4 5 6 7 8 9 as values as a starting point.
Now, I'm not trying to be rude but my teacher is not very good, we basically spend 2 hours on a single problem without her doing much explaining. Other than that I started with C++ Primer and Programming: Principles and Practice Using C++ so I believe I'll be able to learn a lot on my own.
Anyhow my questions are probably quite stupid, but if anyone feels like helping, here they are:
My /**/ commented for loop for anti-diagonal value gives me a wrong sum. I'm assuming it has something to do with the nature of for-loops or I just type it out wrong, but I didn't figure it out yet.
2.The teacher's solution for calculating the anti-diagonal values is the following:
for (i = 0; i < row_num; ++i)
for (j = 0; j < col_num; ++j)
if (i + j == row_num - 1)
anti-diagonal += A[i][j];
How is it different from my approach? I believe mine is simpler and works better.
3.In line:
int sumRows[row_num] = { 0 };
Why do {} have to be used? Our teacher didn't bother with explaining that. I tried without {} but I got an error.
Here is the full code for my version:
#include "../../std_lib_facilities.h"
#include <iostream>
using namespace std;
#define row_num 3 //no. of rows
#define col_num 3 //no. of columns
int main()
{
int i = 0;
int j = 0;
int diagonal = 0;
int antidiagonal = 0;
int sumRows[row_num] = { 0 };
int sumCol[col_num] = { 0 };
int A[row_num][col_num];
//Input to matrix
for(i=0; i<row_num; i++)
for (j = 0; j < col_num; j++)
{
cout << "A[" << i << "]" << "[" << j << "]: ";
cin >> A[i][j];
sumRows[i] += A[i][j];
sumCol[j] += A[i][j];
}
cout << endl;
//Print out the matrix
for (i = 0; i < row_num; i++)
{
for (j = 0; j < col_num; j++)
cout << A[i][j] << '\t';
cout << endl;
}
//prints sum of rows
for (i = 0; i < row_num; i++)
cout << "Sum of row " << i + 1 << " "<< sumRows[i] << endl;
//prints sum of columns
for (j = 0; j < row_num; j++)
cout << "Sum of column " << j + 1 << " " << sumCol[j] << endl;
//Sum of diagonal values
for (i = 0; i < row_num; i++)
diagonal += A[i][i];
//Sum of antidiagonal values
for (i = 0, j = 2; i < row_num, j >= 0; i++, j--)
antidiagonal += A[i][j];
/*for(i=0; i<row_num; i++)
for (j = 2; j >= 0; j--)
{
antidiagonal += A[i][j];
}
*/
cout << "\nSum of diagonal values: " << diagonal << endl;
cout << "Sum of antdiagonal values: " << antidiagonal << endl;
return 0;
}
1) Your commented out loop sums all values, not just those along the antidiagonal.
2) It is different from your approach in that it will iterate over every value in the matrix, but then it will only add to the total if it detects it is in one of the appropriate cells. Your solution only iterates over the appropriate cells and doesn't have to evaluate any ifs, so it will be more efficient. However, you need to change your loop condition to i < row_num && j >= 0. Using a comma here will discard the result of one of the checks.
3) int sumRows[row_num] = { 0 }; initializes the whole sumRows array with 0's.
1) This
for(i=0; i<row_num; i++)
for (j = 2; j >= 0; j--)
{
antidiagonal += A[i][j];
}
is wrong, because for i=0 you iterate through all j values, ie
i=0 , j=2,1,0 then i=1
2) Your teachers loop is easier to read and correct. Yours has a wrong break condition:
for (i = 0, j = 2; i < row_num, j >= 0; i++, j--)
^------------------------ WRONG
Read about the comma operator to understand what is actually going on here. You just didnt realize the problem, because the two conditions are by chance equivalent.
3) You dont have to use it, it is just a new and fancy way to initialize the array.