Vector dot product calculation wrong sum - c

I want to make a program that can calculate the vectors with the dot product but my sum is always 0 what did I do wrong in this code? I'm new to pointers and functions if that is important to you. I coded everything only in the main function and it worked but I want the calculation in another function because its clearer instead of writing everything in the main function. I compiled it with -Wall and -Werror and I got 0 warnings.
Would be nice if you could help me here :)
Here is the code:
#include<stdio.h>
#include<stdlib.h>
double calculation(int o, double *a, double *b, int sum) {
int i;
for(i=0;i<o;++i) {
printf("Components of first vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &a[i]);
}
for(i=0;i<o;++i) {
printf("Components of second vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &b[i]);
}
for(i=0;i<o;++i) {
sum += a[i] * b[i];
}
return(0);
}
int main() {
int o;
int sum=0;
printf("How many dimensions should the vectors have?\n");
scanf("%d", &o);
double *a = malloc(o * sizeof(double));
double *b = malloc(o * sizeof(double));
if(a==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
if(b==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
calculation(o,a,b,sum);
printf("The dot product is: %d\n", sum);
free(a);
free(b);
a=NULL;
b=NULL;
return(0);
}

In C, variables are passed by value. That means that when you change the value of sum in calculation you only change a local copy.
The idiomatic way when you only need one value is to return it:
double calculation(int o, double *a, double *b) {
double sum = 0.;
...
return sum;
}
and in main:
...
double sum = calculation(o, a, b);
...
Alternatively, if you need to return multiple values, you can pass pointers to the output variables

In double calculation(int o, double *a, double *b, int sum) the last argument is passed by value1. That is, when you call calculation(..., sum);, the variable sum is copied and then passed to the function.
Inside this function, you're modifying sum, but this only modifies the copy of the original variable that was passed. To solve this, pass a pointer or just return the sum from your function.
Actually, all arguments are passed by value. The second and the third ones just happen to be pointers.

This function
double calculation(int o, double *a, double *b, int sum) {
should change
double calculation(int o, double *a, double *b, double & sum) {

The problem with your code is that the sum is a local variable in the calculation function. So when you return back to main your variable is destructed and the sum in main is still 0.
Also if you are getting floating point values for dimensions then you must use double for sum too.
One possible solution could be like this:
#include<stdio.h>
#include<stdlib.h>
double calculation(int o, double *a, double *b) {
int i;
double sum =0.0;
for(i=0;i<o;++i) {
printf("Components of first vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &a[i]);
}
for(i=0;i<o;++i) {
printf("Components of second vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &b[i]);
}
for(i=0;i<o;++i) {
sum += a[i] * b[i];
}
return sum;
}
int main() {
int o;
double sum =0;
printf("How many dimensions should the vectors have?\n");
scanf("%d", &o);
double *a = malloc(o * sizeof(double));
double *b = malloc(o * sizeof(double));
if(a==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
if(b==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
sum = calculation(o,a,b);
printf("The dot product is: %lf\n", sum);
free(a);
free(b);
a=NULL;
b=NULL;
return(0);
}
Or you can pass the address of sum to calculation function as:
#include<stdio.h>
#include<stdlib.h>
void calculation(int o, double *a, double *b,double *sum) {
int i;
for(i=0;i<o;++i) {
printf("Components of first vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &a[i]);
}
for(i=0;i<o;++i) {
printf("Components of second vector\n");
printf("Component %d: ", i+1);
scanf("%lf", &b[i]);
}
for(i=0;i<o;++i) {
*sum += a[i] * b[i];
}
}
int main() {
int o;
double sum=0;
printf("How many dimensions should the vectors have?\n");
scanf("%d", &o);
double *a = malloc(o * sizeof(double));
double *b = malloc(o * sizeof(double));
if(a==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
if(b==NULL) {
printf("Memoryallocation was not successfull!!!");
return(1);
}
calculation(o,a,b,&sum);
printf("The dot product is: %lf\n", sum);
free(a);
free(b);
a=NULL;
b=NULL;
return(0);
}

Related

Why don't float operations work properly?

I'm new to C, but i have previously coded in C++ and C#. I have written this code as an assignment, but the float operations don't work properly. What it's supposed to do is, by entering two positive integers, n and m, the end result should be this a sum of a sum with n and the square root of a multiplication.
My problem is that, even though the first sum works, both the multiplication and the square root (and in the end the final sum) don't work. In the end, whatever two numbers n and m i write, the sum will be ok and the other two will be completely innaccurate - either 1, both the multiplication and the final sum, or something that makes no sense (to be precise, "1.#INF00").
This is the code i have written. Does anybody know what i did wrong, or how can I fix this?
float sum(int n)
{
float s = 0;
for(float i = 1; i<=(float)n; i++)
{
s += (2*i)/(3*i*i+4);
}
return s;
}
float multiplication(int m)
{
float p = 1;
for(float j = 1; j <= (float)m; j++)
{
p *= (float)(j*j+1);
}
return p;
}
int main()
{
int n;
int m;
scanf("%i", &n);
scanf("%i", &m);
float s = sum(&n);
float p = multiplication(&m);
float e = s + (float)sqrt(p);
printf("The sum is %f \n", s);
printf("The multiplication is %f \n", p);
printf("The final expression is %f \n", e);
getch();
return 0;
}
You should pass the integer values, not pointers, to the functions sum and multiplication.
float sum(int n)
{
float s = 0;
for(float i = 1; i<=(float)n; i++)
{
s += (2*i)/(3*i*i+4);
}
return s;
}
float multiplication(int m)
{
float p = 1;
for(float j = 1; j <= (float)m; j++)
{
p *= (float)(j*j+1);
}
return p;
}
int main()
{
int n;
int m;
scanf("%i", &n);
scanf("%i", &m);
float s = sum(n); /* pass an integer, not a pointer */
float p = multiplication(m); /* pass an integer, not a pointer */
float e = s + (float)sqrt(p);
printf("The sum is %f \n", s);
printf("The multiplication is %f \n", p);
printf("The final expression is %f \n", e);
getch();
return 0;
}

Bisection method. Optimise function in C code

I have a comment from my teacher related to my code for bisection method. He said "The number of calculations of the function is not optimised. In fact, on each iteration, the function is calculated three times, although it would be enough once."
Could you please help me to optimise the calculations. I actually don't even see at which point the function is calculated 3 times.
#include<stdio.h>
#include<math.h>
#include<time.h>
double f(double x); //Function
int res(int i, double a, double b, double ξ, double ε1, double ε2); //Print result
double Bisection(double a, double b, double ε1, double ε2); //Bisection method
int main()
{
double a=-10, b=0, ξ, h=0.5, α, x1, x2, ε1, ε2;
int i=0;
printf("\nf(x) = 2^x - 2 * cos(x)");
printf("\nStart of the interval a = %.0lf", a);
printf("\nEnd of the interval b = %.0lf", b);
printf("\nEnter error ε1 for function = ");
scanf("%lf", &ε1);
printf("Enter error ε2 for argument = ");
scanf("%lf", &ε2);
printf("\n\nSOLUTION:");
//selection of roots
x1=a;
x2=x1+h;
while (x2<=b)
{
if ((f(x1)*f(x2))<0)
{
i++;
printf("\n\n%d) %d root of the function is in the interval [%.1f, %.1f]\n",i, i, x1, x2);
printf("\nn\t a\t\t b\t\t ξ\t f(ξ)\t ε1\t\t ε2\n");
Bisection(x1,x2,ε1,ε2); //Bisection method
}
x1=x2;
x2=x1+h;
}
return 0;
}
//Function
double f(double x)
{
double y;
y=pow(2,x)-2*cos(x);
return y;
}
//Print result
int res(int i, double a, double b, double ξ, double ε1, double ε2)
{
printf("%d\t%10.7f %10.7f %10.7f %10.7f %e %e\n", i, a, b, ξ, f(ξ), ε1, ε2);
return 0;
}
//Bisection method
double Bisection(double a, double b, double ε1, double ε2)
{
double ξ=(a+b)/2; //Middle of the interval
double α;
int i=0;
if (f(ξ)==0)
{
printf("Root: %f \n\n", ξ);
}
else
{
while ((fabs(f(ξ))>ε1) && ((fabs(b-a)/2)>ε2)) //The accuracy of the definition of the root
{
if ((f(a)*f(ξ))<0)
{
b=ξ;
}
else
{
a=ξ;
}
ξ=(a+b)/2;
res(i+1, a, b, ξ, ε1, ε2); //Print results
i++;
}
printf("Root ξ=%.7f found after %d iterations\n", ξ, i);
printf("Function f(ξ)=%.10f found after %d iterations\n", f(ξ), i);
}
return 0;
}
Results
Only including relevant lines
Replace:
double Bisection(double a, double b, double ε1, double ε2)
{
double ξ=(a+b)/2;
if (f(ξ)==0)
else
{
while ((fabs(f(ξ))>ε1) && ((fabs(b-a)/2)>ε2))
{
if ((f(a)*f(ξ))<0)
ξ=(a+b)/2;
}
}
with
double Bisection(double a, double b, double ε1, double ε2)
{
double ξ=(a+b)/2;
double val = f(ξ); // Here is the magic
if (val==0)
else
{
while ((fabs(val)>ε1) && ((fabs(b-a)/2)>ε2))
{
if ((f(a) * val )<0)
ξ=(a+b)/2;
val = f(ξ); // And here
}
}
It's not really some secret trick we're talking about. It's only about saving the return value in a variable and use that variable instead of a function call whenever possible. If the argument to the function changes, then you need to execute the function again. Here is a simple example that makes a string uppercase.
void uppercase(char *str) {
// Bad, because it's not necessary to calculate the string
// length every iteration.
for(size_t i=0; i<strlen(str); i++)
str[i] = toupper(str[i]);
}
// Instead, do this
void uppercase(char *str) {
size_t len = strlen(str); // Precalculate and reuse in loop
for(size_t i=0; i<len; i++)
str[i] = toupper(str[i]);
}

Why `pow(sum,1/2)` is not giving me the same result as `sqrt(sum))`?

In the code at the end, there is a function at the bottom called general_norm that uses the following print() functions:
printf(" %f",sqrt(sum));
printf(" %f",pow(sum,1/2));
While sqrt(sum)) is giving me the correct result, I don't understand why pow(sum,1/2) is not considering that √x = x½.
Could you help me figure out what I am missing? Thank you! :-)
#include <stdio.h>
#include <math.h>
void print_vector(int N,float * V);
void save_vector(int N,float * V);
void absolute_values(int N,float * V, float * VABS);
void maximum_value(int N, float * VABS);
void general_norm(int N, float * VABS);
int main(void)
{
const int n=4;
int i;
float v[n],vabs[n];
puts("Enter the 5 components of the vector:");
save_vector(n, v);
puts("\nThe vector is:");
print_vector(n, v);
puts("\nThe absolute vector is:");
absolute_values(n, v, vabs);
puts("\nThe maximum value is:");
maximum_value(n, vabs);
puts("\nThe general norm is:");
general_norm(n, vabs);
return 0;
}
void save_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
scanf("%f",V+i);
}
void print_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
printf(" %.2f ",*(V+i));
}
void absolute_values(int N, float *V, float *VABS)
{
int i;
for(i=0;i<N;i++)
{
VABS[i]=((V[i]<0)?-V[i]:V[i]);
printf(" %f", VABS[i]);
}
}
void maximum_value(int N, float * VABS)
{
int i;
float maximum;
maximum = VABS[0];
for (i = 1; i < 4; i++)
{
if (VABS[i] > maximum)
{
maximum = VABS[i];
}
}
printf(" %f", maximum);
}
void general_norm(int N, float * VABS)
{
int i;
float sum;
for (i = 0; i < 4; i++)
{
sum=sum+pow(VABS[i],2);
}
printf(" %f",sqrt(sum));
printf(" %f",pow(sum,1/2));
}
Just leaving here the answer 1201ProgramAlarm gave me:
Integer math. 1/2 is 0. Either use 0.5, or force the type 1.0 / 2.0.
1.0 / 2 would also work.

How can I get the maximum value of all the components in a vector?

I just wrote a program that saves a 4-component vector entered by the user (using a function called save_vector) and prints it (using a function called print_vector). Also, it creates a new vector called vabs that has the same components but in absolute value (positive).
Now I am trying to find the maximum value in the vabs vector by using the function maximum value. However, I only get this result: 0.000000 even though I am entering non-zero components in the vector. Could you help me figure out what I am missing? Thank you! :-)
#include <stdio.h>
void print_vector(int N,float * V);
void save_vector(int N,float * V);
void absolute_values(int N, float * V);
void maximum_value(int N, float * VABS);
int main(void)
{
const int n=5;
int i;
float v[n],vabs[n];
puts("Enter the 5 components of the vector:");
save_vector(n, v);
puts("\nThe vector is:");
print_vector(n, v);
puts("\nThe absolute vector is:");
absolute_values(n, v);
puts("\nThe maximum value is:");
maximum_value(n, vabs);
return 0;
}
void save_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
scanf("%f",V+i);
}
void print_vector(int N, float * V)
{
int i;
for(i=0;i<N;i++)
printf(" %.2f ",*(V+i));
}
void absolute_values(int N, float * V)
{
int i;
float VABS[N];
for(i=0;i<N;i++)
{
VABS[i]=((V[i]<0)?-V[i]:V[i]);
printf(" %f", VABS[i]);
}
}
void maximum_value(int N, float * VABS)
{
int i;
float maximum;
maximum = VABS[0];
for (i = 1; i < 5; i++)
{
if (VABS[i] > maximum)
{
maximum = VABS[i];
}
}
printf(" %f", maximum);
}
The code is not working as intended because:
You are passing an empty vector vabs to the function which should find the max_value.
In the function that assigns the absolute values, your VABS vector is local, it will be lost as the function returns, you need to pass the main vabs vector to the function as an argument so that the changes can be saved and used to find the max value:
void absolute_values(int N, float *V, float *VABS) //pass vabs as argument
{
int i;
//float VABS[N]; this is local, it's lost when the function returns
for (i = 0; i < N; i++)
{
VABS[i] = ((V[i] < 0) ? -V[i] : V[i]);
printf(" %f", VABS[i]);
}
}
And in main:
int main(void)
{
//...
puts("\nThe absolute vector is:");
absolute_values(n, v, vabs);
puts("\nThe maximum value is:");
maximum_value(n, vabs);
return 0;
}
Here is a running sample of the fixed code.

Am I properly passing parameters and passing by reference?

I am getting no output for the grosspay and taxespaid functions for this programming assignment I am writing to keep track of employee payroll. I am just wondering if I am properly passing parameters and passing by reference, which is the method we are supposed to use. My class doesn't meet often and the book sucks so I would appreciate any advice.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
void userinput(char name[][20], int hoursworked[], float rate[]);
void calculatepay(float rate[], int hoursworked[]);
float tax(float grosspay[]);
float totalpay(float grosspay[], float taxespaid[]);
void print(char name[][20], float rate[], int hoursworked[], float grosspay[], float sum, float taxespaid[]);
int main(){
int hoursworked[]={};
float rate[]={};
char name[][20]={};
float grosspay[]={};
float taxespaid[]={};
float sum;
userinput(name, hoursworked, rate);
calculatepay(rate, hoursworked);
sum = tax(grosspay);
totalpay(grosspay, taxespaid);
print(name, rate, hoursworked, grosspay, sum, taxespaid);
return (0);
}
void userinput(char name[][20], int hoursworked[], float rate[]){
for(int i=0; i<SIZE; i++){
printf("Enter name: ");
scanf("%s", &name[i] , 20);
if(name[i][0] == '-' && name[i][1] == '1'){
break;
}
printf("Enter hours worked: ");
scanf("%d", &hoursworked[i]);
if(hoursworked[i] == -1){
break;
}
printf("Enter hourly rate: ");
scanf("%f", &rate[i]);
if(rate[i] == -1){
break;
}
puts("\n");
}
}
void calculatepay(float rate[], int hoursworked[]){
float grosspay[]={};
for(int i=0; i<SIZE; ++i){
if(hoursworked[i]<=40){
grosspay[i] = rate[i] * hoursworked[i];
}
else{
grosspay[i] = (40*rate[i])+((hoursworked[i] - 40)*1.5*rate[i]);
}
}
}
float tax(float grosspay[]){
float taxespaid[]={};
for(int i=0; i<SIZE; ++i){
taxespaid[i] = grosspay[i]*0.2;
return taxespaid[i];
}
return 0;
}
float totalpay(float grosspay[], float taxespaid[]){
float sum = 0.0;
for (int i=0; i<SIZE; i++)
{
sum=sum+(grosspay[i] - taxespaid[i]);
}
return sum;
}
void print(char name[][20], float rate[], int hoursworked[], float grosspay[], float sum, float taxespaid[]){
for(int i=0; i<SIZE; i++){
printf("Pay to: %s\n", name[i] , 20);
if(name[i][0] == '-' && name[i][1] == '1'){
break;
}
printf("Hours worked: %d\n", hoursworked[i]);
if(hoursworked[i] == -1){
break;
}
printf("Hourly rate: %.2f\n", rate[i]);
if(rate[i] == -1){
break;
}
if(hoursworked[i]<=40){
printf("Gross Pay: %.2f\n", grosspay[i]);
}
else
{
printf("Gross Pay: %.2f\n", grosspay[i]);
printf("Base Pay: %.2f\n", rate[i]*40);
printf("Overtime Pay: %.2f\n", grosspay[i] - (rate[i]*40));
}
printf("Taxes paid: %.2f\n", taxespaid[i]);
printf("Net pay: %.2f\n\n", grosspay[i] - taxespaid[i]);
}
printf("Total paid to all employees: %.2f\n", sum);
}
I hate to be the bearer of bad news, but there is no pass-by-reference in C. The only method of parameter passing that C defines is pass-by-value, in 6.5.2.2p4:
In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.
Perhaps you intended to ask about C++, in which case... No, you're not using pass-by-reference.
Otherwise, if you intended to ask how C mimics pass-by-reference, it is by using pointers (that is, the parameters have pointer types and pointer values).
In void userinput(char name[][20], int hoursworked[], float rate[]);, for example, name, hoursworked and rate are all pointer types. The values that are passed will be pointer values. The pointer values point into the objects that are to be modified, so the same outcome is possible (that is, the changes that are made to the array are still visible once the function returns).
In case you're curious as to why this doesn't technically qualify as pass-by-reference, it's because the unary *pointer or array[subscript] (or pointer[subscript] operators are required to change the value pointed to, where-as when pass-by-reference is used you should merely be able to assign a value without those like: array = value;. It makes more sense if you look at it as a test in writing a swap function:
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
If you try calling this function, you will notice that it hasn't successfully swapped its arguments. If you were to use pass-by-value, those three lines would have swapped its arguments. For example, in C++:
void swap(int& x, int& y) {
int temp = x;
x = y;
y = temp;
}
This will swap the arguments. All I had to change was the function signature; I didn't have to change the way the function is used or the code in the function itself... That is pass-by-reference.
When I declared the variables before main() and initialised the arrays with SIZE then it worked fine :)
#define SIZE 5
void userinput(char name[][20], int hoursworked[], float rate[]);
void calculatepay(float rate[], int hoursworked[]);
float tax(float grosspay[]);
float totalpay(float grosspay[], float taxespaid[]);
void print(char name[][20], float rate[], int hoursworked[], float grosspay[], float sum, float taxespaid[]);
int hoursworked[SIZE];
float rate[SIZE];
char name[SIZE][20];
float grosspay[SIZE];
float taxespaid[SIZE];
float sum;
int main(){
userinput(name, hoursworked, rate);
calculatepay(rate, hoursworked);
sum = tax(grosspay);
totalpay(grosspay, taxespaid);
print(name, rate, hoursworked, grosspay, sum, taxespaid);
return (0);
}
void userinput(char name[][20], int hoursworked[], float rate[]){
int i;
for(i=0; i<SIZE; i++){
printf("Enter name: ");
scanf("%s", &name[i] , 20);
if(name[i][0] == '-' && name[i][1] == '1'){
break;
}
printf("Enter hours worked: ");
scanf("%d", &hoursworked[i]);
if(hoursworked[i] == -1){
break;
}
printf("Enter hourly rate: ");
scanf("%f", &rate[i]);
if(rate[i] == -1){
break;
}
puts("\n");
}
}
void calculatepay(float rate[], int hoursworked[]){
float grosspay[SIZE];
int i;
for(i=0; i<SIZE; ++i){
if(hoursworked[i]<=40){
grosspay[i] = rate[i] * hoursworked[i];
}
else{
grosspay[i] = (40*rate[i])+((hoursworked[i] - 40)*1.5*rate[i]);
}
}
}
float tax(float grosspay[]){
int i;
float taxespaid[SIZE];
for(i=0; i<SIZE; ++i){
taxespaid[i] = grosspay[i]*0.2;
return taxespaid[i];
}
return 0;
}
float totalpay(float grosspay[], float taxespaid[]){
float sum = 0.0;
int i;
for (i=0; i<SIZE; i++)
{
sum=sum+(grosspay[i] - taxespaid[i]);
}
return sum;
}
void print(char name[][20], float rate[], int hoursworked[], float grosspay[], float sum, float taxespaid[]){
int i;
for(i=0; i<SIZE; i++){
printf("Pay to: %s\n", name[i] , 20);
if(name[i][0] == '-' && name[i][1] == '1'){
break;
}
printf("Hours worked: %d\n", hoursworked[i]);
if(hoursworked[i] == -1){
break;
}
printf("Hourly rate: %.2f\n", rate[i]);
if(rate[i] == -1){
break;
}
if(hoursworked[i]<=40){
printf("Gross Pay: %.2f\n", grosspay[i]);
}
else
{
printf("Gross Pay: %.2f\n", grosspay[i]);
printf("Base Pay: %.2f\n", rate[i]*40);
printf("Overtime Pay: %.2f\n", grosspay[i] - (rate[i]*40));
}
printf("Taxes paid: %.2f\n", taxespaid[i]);
printf("Net pay: %.2f\n\n", grosspay[i] - taxespaid[i]);
}
printf("Total paid to all employees: %.2f\n", sum);
}

Resources