1


I kind of got stuck here with a little problem:

I study for my exam and my task was to write a program that can do the following:
There are two given vectors x and y who are an element of R^(n) and each of them is a double array of the length n, with n being an element of N. In addition there is a double variable a as element of R given.

I need to write four functions vec_plus, vec_mult, dotprod and norm2, which have the following purpose:
(My problems so far are only considering vec_plus and vec_mult)

1. vec_plus has to calculate x + a * y (element of R^n) and save it in x!

2. vec_mult has to calculate a * x (element of R^n) and save it in x!

3. dotprod has to calculate the scalar product <x,y> and return it.

4. norm2 has to calculate the euclidean norm ||x|| = sqrt(<x,x>) and return it.

Now here is my code:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

double vec_plus(double* x, double* y, double a, unsigned int n) {
    unsigned int i;
    for (i = 0; i < n; i++) { 
        x[i] = x[i] + (a * y[i]);
    }
    return *x;
}

double vec_mult(double* x, double a, unsigned int n) {
    unsigned int i;
    for (i = 0; i < n; i++) { x[i] = a * x[i]; }
    return *x;
}

double dotprod(double* x, double* y, unsigned int n) {
    unsigned int i;
    double z = 0;
    for (i = 0; i < n; i++) { z = z + x[i] * y[i]; }
    return z;
}

double norm2(double* x, unsigned int n) {
    unsigned int i;
    double z = 0;
    for (i = 0; i < n; i++) { z = z + hypot(x[i], x[i]); }
    return z;
}

int main(void) {
    unsigned int n;
    unsigned int i;
    printf("Please enter n = "); scanf_s("%u", &n);
    double* x, * y, a;
    x = (double*)malloc(n * sizeof(double));
    y = (double*)malloc(n * sizeof(double));
    if (x == NULL || y == NULL) { printf("malloc error\n"); exit(EXIT_FAILURE); }
    for (i = 0; i < n; i++) {
        printf("Please enter x_%d = ", i); scanf_s("%lf", &x[i]);
    }
    for (i = 0; i < n; i++) {
        printf("Please enter y_%d = ", i); scanf_s("%lf", &y[i]);
    }
    printf("Please enter your scalar a = "); scanf_s("%lf", &a);

    for (i = 0; i < n; i++) {
        printf("\nvec_plus_%d = %lf", i, vec_plus(x, y, a, n));
    }
    for (i = 0; i < n; i++) {
        printf("\nvec_mult_%d = %lf", i, vec_mult(x, a, n));
    }

    free(x); free(y);
    return 0;
}


I have a feeling that I might have messed up somewhere in the memory allocation but I am not able to detect my error and I am also not sure.

As example I will show you my input, the output I'd expect and the actual output.

*My input*
Please enter n = 3
Please enter x_0 = 1
Please enter x_1 = 2
Please enter x_2 = 3
Please enter y_0 = 3
Please enter y_1 = 2
Please enter y_2 = 1
Please enter your scalar a = 6


*Output I expect/want*
vec_plus_0 = 19.000000
vec_plus_1 = 14.000000
vec_plus_2 = 9.000000
vec_mult_0 = 6.000000
vec_mult_1 = 12.000000
vec_mult_2 = 18.000000


*Actual output*
vec_plus_0 = 19.000000
vec_plus_1 = 37.000000
vec_plus_2 = 55.000000
vec_mult_0 = 330.000000
vec_mult_1 = 1980.000000
vec_mult_2 = 11880.000000


Now here is the way, how I imagined my code would work when I wrote it:
Lets say I took the same input as mentioned.

*My input*
Please enter n = 3
Please enter x_0 = 1
Please enter x_1 = 2
Please enter x_2 = 3
Please enter y_0 = 3
Please enter y_1 = 2
Please enter y_2 = 1
Please enter your scalar a = 6


What I imagine happens in this part of the code:

double vec_plus(double* x, double* y, double a, unsigned int n) {
    unsigned int i;
    for (i = 0; i < n; i++) { 
        x[i] = x[i] + (a * y[i]);
    }
    return *x;
}

function gets passed values of x, y, the scalar a and the length n.
now we get in the for loop with:
x[0] = x[0] + (a * y[0]); //I know the parentheses are redundant but i kind of tried all I could
x[0] = 1 + (6 * 3) // x[0] = 19

x[1] = x[1] + (a * y[1]);
x[1] = 2 + (6 * 2) // x[1] = 14

x[2] = x[2] + (a * y[2]);
x[2] = 3 + (6 * 1) // x[2] = 9


Now obviously this is not the actual output. Can someone please help me fix this problem?
Thanks in advance and have a great day!

  • You are aware, that your addition and others are modifying the operands (the original arrays), right? Also `return *x;` is returning the *first element* of `x`. A result of vector addition should be a vector. – Eugene Sh. Jan 20 '20 at 16:37
  • [Do I cast the result of malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – RobertS supports Monica Cellio Jan 20 '20 at 16:37
  • You should use a debugger to detect how and where the values come to these different values than you´d expected. – RobertS supports Monica Cellio Jan 20 '20 at 16:48
  • @EugeneSh. I also thought about the issue of modifying the operands in my additions but I didn't knew how to fix this. Should I declare a new array in the function and save it there and return from there? I could do that but in the task it is demanded from me to save it in the array x, this is why I don't know what to do. I originally declared my functions vec_plus and vec_mult as double* functions but somehow I tried out so many new stuff that I feel I messed my code up even more. – DeathDeliveryGuy Jan 20 '20 at 16:54
  • @RobertS-ReinstateMonica yes that makes sense to me. But I never used a debugger before and don't know how this works. I will try to find some tutorial for this. – DeathDeliveryGuy Jan 20 '20 at 16:56

1 Answers1

0

vec_plus returns the value of the first element of the array x:

double vec_plus(double* x, double* y, double a, unsigned int n) {
    unsigned int i;
    for (i = 0; i < n; i++) { 
        x[i] = x[i] + (a * y[i]);
    }
    return *x;  // returns value of the first element of x, x[0].
}

So each time you invoke:

printf("\nvec_plus_%d = %lf", i, vec_plus(x, y, a, n));

inside the for-loop in main() you are not getting the expected values of x[0], x[1] and x[2] in that order. You only get and print out the value of x[0] at each iteration.

Furthermore, x[0] is changing each time you call the vec_plus function:

x[i] = x[i] + (a * y[i]);  // x[0] is changing each time vec_plus() is called.

So you do not get the values of x[1] and x[2], you only get the changed value of x[0], which is changing with each call to vec_plus in each iteration in main():

x[i] = x[i] + (a * y[i]);
_________________________

1.Walkthrough, 1. call to vec_plus: 
x[0] = 1 + (6 * 3) // value of x[0] after this statement = 19

2.Walkthrough, 2. call to vec_plus:  
x[0] = 19 + (6 * 3) // value of x[0] after this statement = 37

3.Walkthrough, 3. call to vec_plus:  
x[0] = 37 + (6 * 3) //  value of x[0] after this statement = 55

The only things you need to do, is changing the return value of vec_plus:

return x[i];

and wrap the iteration inside vec_plus:

    unsigned int i;
    for (i = 0; i < n; i++) { 
        x[i] = x[i] + (a * y[i]);
    }

Instead, use the i from the iteration in main(). Notice the i as argument/parameter of vec_plus:

double vec_plus(double* x, double* y, double a, unsigned int n, unsigned int i) {

    x[i] = x[i] + (a * y[i]);

    return x[i];  
}

for-loop in main():

    for (i = 0; i < n; i++) {
        printf("\nvec_plus_%d = %lf", i, vec_plus(x, y, a, n, i));
    }

The same applies to the vec_mult function.

  • Thanks for this detailed answer, it solved my problem with *vec_plus* but now I have the problem that I still have a changed x[0] and when my program invokes *vec_mult* it carries on with the same mistakes as I had before. I thin I will declare a new double array and store the values of the user input from **x** in it and use this to pass the values again back to **x** before I allow my program to invoke *vec_mult*. I think this is a very ugly solution of mine, if you have an better idea or help, I am glad to learn :) Thanks again for your effort and help. – DeathDeliveryGuy Jan 21 '20 at 12:37
  • @DeathDeliveryGuy The only problem is that you change the values of `x` inside the functions and use the actual array values as return value, but you do not need to do so. You can define `vec_plus` and the other functions like: `double vec_plus(double* x, double* y, double a, unsigned int n, unsigned int i) { return x[i] + (a * y[i]); } ` or `double vec_plus(double* x, double* y, double a, unsigned int n, unsigned int i) { double j; j = x[i] + (a * y[i]); return j; } ` and the problem is solved. I hope you can read the text in this horizontal typography. – RobertS supports Monica Cellio Jan 21 '20 at 12:59
  • True, this is a way more elegant solution. My only problem is that the task expects me to save the input inside **x**, I don't know why. Probably it is supposed to teach me something but I would have never come to an solution like this if I would code on a project or anything similar. I don't know what would be the advantage of overwriting input inside an array and therefore losing the functionality of that very same array for other functions. Thanks! – DeathDeliveryGuy Jan 21 '20 at 13:06
  • @DeathDeliveryGuy I can not understand, what for a task this should be to overwrite values, which **need** to be used later, unless this is the thing the task is ment for (to calculate values made by previous calculations). But it doesn´t seem that this is the thing which should be used here. You have to read carefully: *"to save the input inside x"* is not the same *"to save the output inside x"*. Maybe it is just a misunderstanding of yours. – RobertS supports Monica Cellio Jan 21 '20 at 13:12
  • the task is written in German as follow: "i) vec_plus berechnet die Vektorsumme x + a * y (element von) R^n und speichert sie in x."; which means as much as: "vec_plus calculates the vector sum x + a * y (element of) R^n and saves it in x." – DeathDeliveryGuy Jan 21 '20 at 13:20