#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct vector
{
double x;
double y;
double z;
};
struct vector *array;
double length(struct vector*);
int main()
{
int num,i;
double xin;
double yin;
double zin;
char buffer[30];
char buffer2[30];
printf("Enter number of vectors:");
fgets(buffer, 30, stdin);
sscanf(buffer, "%d", &num);
array = malloc( sizeof(struct vector) * num);
for(i=0;i<=num;i++)
{
printf("Please enter x y z for the vector:");
fgets(buffer2,100,stdin);
sscanf(buffer2, " %lf %lf %lf", &xin, &yin, &zin);
array[i].x = xin;
array[i].y = yin;
array[i].z = zin;
}
for(i=0;i<=num;i++)
{
printf( "Vector:%lf %lf %lf has a length of %lf\n", array[i].x, array[i].y, array[i].z, length(&array[i]));
}
}
double length(struct vector* vec)
{
return sqrt( (vec->x * vec->x) + (vec->y * vec->y) + (vec->z * vec->z) );
}
Ok the above code is almost finished it asks user for number of vectors then it asks user for the values of those vectors it then will calculate the length and print it out correspondingly.
I am trying to get some error checking in here but I cannot seem to get it...I looked up every possible return value for fgets and sscanf I just cant seem to get it
Defensive features
FIRST printf-------input should only be a single number greater than 0 and EOF should return a message like printf("enter a number--bye!") so I tried
while( sscanf(buffer, "%d", &num) ==1 && num > 0 )
but it still works if something like 3dadswerudsad is entered
also when the user is entering the 3 values for the vector if anything at all other than 3 doubles are entered for a vector the program should terminate with a message so I tried
while( sscanf(buffer2, "%lf %lf %lf", &xin, &yin, &zin) ==3 )
but it doesn't check for these incorrect inputs!!
I am going crazy
You are almost right, you need to name the formal and the function and to use it appropriately:
double veclength (struct vector v) {
return sqrt( (v.x * v.x) + (v.y * v.y) + (v.z * v.z) );
}
for efficiency and other reasons you might consider passing a pointer (to a constant vector, since you don't modify it)
double veclengthptr (const struct vector* v) {
return sqrt( (v->x * v->x) + (v->y * v->y) + (v->z * v->z) );
}
and then you could later use veclength(array[i]) or veclengthptr(array+i) (same as veclengthptr(&a[i]))
You should want to give prototypes (perhaps in some header file) before using these functions :
double veclength (struct vector);
double veclengthptr (const struct vector*);
Notice that for efficiency reasons you might want to declare these prototypes as static inline (and give their implementation in the same translation unit), so to ask for inline functions:
static inline double veclength (struct vector);
Take the habit of compiling with all warnings & debug info, e.g. gcc -Wall -Wextra -g
Regarding your use of sscanf(3) as sscanf(buf, "%d", &num) notice that if buf contains 3dxde it succeeds by reading 3 into num (with dxde unparsed). You might want to use %n in sscanf (read its documentation!) or use strtol(3)
The function could be implemented as follows.
double length(struct vector vec)
{
return sqrt( vec.x*vec.x + vec.y*vec.y + vec.z*vec.z );
}
Related
Firstly, i don't believe this is related to precision, I think the variable is losing scope somehow?
The function below, header file sorting.h:
#ifndef SORTING_H
#define SORTING_H
/*===========================================================================
Function find_median
Description: median values in a sorted array.
==========================================================*/
float find_median(float values[],int n );
#endif /* SORTING_H */
Implementation file sorting.c :
#include "sorting.h"
float find_median(float values[],int n)
{
float val = 0.0f;
// check for even case
if (n % 2 == 0)
{
val = (float)values[n/2];
}
else
{
int low_index = (n)/2;
int high_index= low_index + 1;
val = (values[low_index] + values[high_index])/2.0f;
}
return val;
}
Main entry, main.c:
int main(int argc, char** argv)
{
//unsorted
float output_array[] = { 3, 17, 13, 6, 9, -1, 10, 10 };
int row_length = sizeof(output_array) / sizeof(output_array[0]);
//sort
quicksort_iterative(output_array, row_length);
float median = 0.0f;
//get the median
median = find_median(output_array, row_length);
printf("median=%f", median);
}
Output:
sorted:,-1.000000,3.000000,6.000000,9.000000,10.000000,10.000000,13.000000,17.000000
median=6422100.000000
I'm attempted to assign the final median value from as a return value & also as tried passing median as a parameter but both attempts return incorrect values.
The median should be 11.
You seem to want to modify median in the calling function. In C++, all you simply do is:
float median(float values[],int n, float& median)
C is a little harder. For that you need a pointer:
float median(float values[],int n, float *median)
{
// ...
*median = val;
// ...
}
// ...
find_median(output_array, row_length, &median);
You are confused on a number of basic fronts. To begin with, look at your function find_median, and specifically at the parameters: (presuming you actually meant to name your function float_median instead of just median as written in sorting.c)
float float_median(float values[],int n, float median);
Your function takes an array of float as the first parameter, that's fine. (but could simply be written as float *values as an array is converted to a pointer on access, see: C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) -- it works the same for C++)
Now your second parameter int n passing the number of elements in the array (also fine), but your third parameter float median, is effectively unused in float_median. Assigning median = val; has zero effect as in C parameters are passed by value so the assignment in float_median of median = val; simply changes the value of the copy of median used in the function and has zero effect on the original median in main(). You are returning the value of median from your function so simply drop the third parameter, e.g.
#include <math.h>
#include "sorting.h"
float find_median (float *values, int n)
{
float val = 0;
// check for even case
if (n % 2 == 0)
val = (float)values[n/2];
else {
int low_index = floor(n-1)/2;
int high_index = ceil(n-1)/2;
val = (values[low_index] + values[high_index]) / 2.;
}
return val;
}
(note: also the denominator is changed from 2 to 2.0 to eliminate the resulting cast to avoid integer division)
Good job on your use of header-guards to prevent multiple inclusion of sorting.h. You only need to update the function prototype to be consistent with dropping the third parameter, e.g.
#ifndef SORTING_H
#define SORTING_H
/*===========================================================================
Function find_median
Description: median values in a sorted array.
==========================================================*/
float find_median (float values[], int n);
#endif /* SORTING_H */
In your main() (I called it sort.c) you attempt to use a quicksort_iterative function that you do not provide. Forget it, just write a quick compare function for the elements in output_array and then use the standard qsort function to sort your array, e.g.
#include <stdio.h>
#include <stdlib.h>
#include "sorting.h"
int compare (const void *a, const void *b)
{
return (*(int*)a > *(int*)b) - (*(int*)a < *(int*)b);
}
int main (void) {
float output_array[] = { 3, 17, 13, 6, 9, -1, 10, 10 };
int row_length = sizeof output_array / sizeof *output_array;
//sort
qsort (output_array, row_length, sizeof *output_array, compare);
float median = find_median (output_array, row_length);
for (int i = 0; i < row_length; i++)
printf (i ? " %g" : "%g", output_array[i]);
putchar ('\n');
printf ("\nmedian = %.2f\n", median);
}
Now just compile:
gcc -Wall -Wextra -pedantic -std=c11 -Ofast sorting.c -o bin/sort sort.c
(note: I would also recommend including -Wshadow to catch any shadowed variables)
Example Use/Output
$ ./bin/sort
-1 3 6 9 10 10 13 17
median = 10.00
Look things over and let me know if you have further questions. If you are on windows or using another compiler than gcc/clang, let me know and I can post equivalent compile options for you.
I think there's problem in your formula. try this.
float median(float values[],int n) //, float& median) //note: notice the & here.
{
float val = 0.0f;
// check for even case
if (n % 2 == 0)
{
//get the average of the 2 mid values.
int high_index = n/2;
int low_index = high_index - 1;
val = (values[high_index] + values[low_index])/2.0f;
//note: 2 is integer, 2.0f is float. there might be problem if you use 2 speciall in division.
printf("even case: val=%f\n", val);
printf("values[%d]=%f\n",low_index);
printf("values[%d]=%f\n",high_index);
}
else
{
val = values[n/2];
printf("odd case: val=%f\n", val);
}
//median = val; //2 way output?
return val;
}
Update
I added logs on the code to trace what's the cause of the problem.
The function is called find_median in the header, but median in the implementation... how does it link?
Then, you are not assigning the result of find_median to the variable median
The goal of the exercise is to calculate a complex number Z according to some formula and create an array of n such complex numbers. Here's the function that calculates Z
double complex convert(double R, int p)
{
double complex Z=0+0*I;
double complex A, B, C;
A=exp(M_PI/4) + 0*I;
B=cos(11*M_PI/6 + 2*p*M_PI) + 0*I;
C=I*sin(R*M_PI/6);
Z=A*((R*B)+C);
return Z;
}
The function that creates the array:
double complex *array_function (double *a, int n)
{
int i;
double complex array[100];
for (i=0; i<n; i++)
{
array[i]=convert(*(a+i),i);
}
return array;
}
And int main:
int main()
{
int N, i;
double complex *new_array[100];
double array[100];
printf("Enter the length of the array = ");
scanf("%d", &N);
for (i=0; i<N; i++)
{
printf("Element number %d is: ", i+1);
scanf("%f", &array[i]);
}
new_array=array_function(array, N); // where I get the error message
printf("The new array is: \n");
for (i=0; i<N; i++)
{
printf("%f + i%f \n", creal(new_array[i]), cimag(new_array[i]));
}
return 0;
}
But I keep getting the same error message: "assignment to expression with array type" in regards to the line: "new_array=array_function(array, N);"
Edit: Here's the edited code:
double complex convert(double R, int p)
{
double complex Z=0+0*I;
double complex A, B, C;
A=exp(M_PI/4) + 0*I;
B=cos(11*M_PI/6 + 2*p*M_PI) + 0*I;
C=I*sin(R*M_PI/6);
Z=A*((R*B)+C);
return Z;
}
double complex *array_function (double *a, int n)
{
int i;
double complex *array = malloc(100 * sizeof *array);
for (i=0; i<n; i++)
{
array[i]=convert(*(a+i),i);
}
return array;
}
int main()
{
int N, i;
double complex *new_array;
double array[100];
printf("Enter the length of the array = ");
scanf("%d", &N);
for (i=0; i<N; i++)
{
printf("Element number %d is: ", i+1);
scanf("%f", &array[i]);
}
new_array=array_function(array, N); // where I get the error message
printf("The new array is: \n");
for (i=0; i<N; i++)
{
printf("%f + i%f \n", creal(new_array[i]), cimag(new_array[i]));
}
return 0;
}
You cannot assign to arrays in C. You can only assign to array elements.
If you want to change arrays dynamically, declare a pointer of the appropriate type and assign the result of malloc and/or realloc.
If you have made the changes to insure you are reading doubles with scanf by adding the 'l' modifier to your %f format specifier (e.g. "%lf") and you have fixed your attempt to return a statically declared array, by declaring a pointer in main() to which you assign the return from array_function, and properly allocated the array in array_function, then your code should be working without crashing. Also, M_PI should be properly typed as double eliminating the integer division concern.
You must VALIDATE ALL USER INPUT (sorry for all caps, but if you learn nothing else here, learn that). That means validating the return of scanf and checking the range of the value entered where appropriate.
Putting those pieces together, you could do something like the following (with the code sufficiently spaced so old-eyes can read it):
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>
#define MAXC 100 /* if you need a constant, define one */
double complex convert (double R, int p)
{
double complex Z = 0 + 0 * I; /* space your code so it is readable */
double complex A, B, C; /* (especially for older eyes......) */
A = exp (M_PI / 4.0) + 0 * I;
B = cos (11 * M_PI / 6.0 + 2 * p * M_PI) + 0 * I;
C = I * sin (R * M_PI / 6.0);
Z = A * ((R * B) + C);
return Z;
}
double complex *array_function (double *a, int n)
{
int i;
double complex *array = calloc (MAXC, sizeof *array); /* allocate */
if (!array) { /* validate allocation succeeded */
perror ("calloc-array");
exit (EXIT_FAILURE);
}
for (i = 0; i < n; i++) /* convert your values */
array[i] = convert (a[i], i);
return array; /* return pointer */
}
int main (void)
{
int N, i;
double complex *new_array; /* declare pointer to receive return */
double array[MAXC];
printf ("Enter array length: ");
if (scanf("%d", &N) != 1 || N > MAXC) { /* VALIDATE ALL USER INPUT */
fprintf (stderr, "error: invalid input or out of range.\n");
return 1;
}
for (i=0; i<N; i++) {
printf (" enter array[%2d]: ", i);
if (scanf("%lf", &array[i]) != 1) { /* VALIDATE ALL USER INPUT */
fprintf (stderr, "error: invalid conversion, array[%d].\n", i);
return 1;
}
}
new_array = array_function (array, N); /* call array_function */
printf("\nThe new array is: \n\n");
for (i=0; i<N; i++) /* output results */
printf (" %10.6f + i%f \n", creal(new_array[i]), cimag(new_array[i]));
free (new_array); /* don't forget to free memory you allocate */
return 0;
}
(note: you should free all memory you allocate)
Example Use/Output
$ ./bin/complex
Enter array length: 5
enter array[ 0]: 1.81
enter array[ 1]: 1.97
enter array[ 2]: .31
enter array[ 3]: 2.51
enter array[ 4]: 6.021
The new array is:
3.43798 + i1.781127
3.74189 + i1.881977
0.58883 + i0.354442
4.76758 + i2.121489
11.43651 + i-0.024116
Look things over and let me know if you have further questions.
double complex *new_array[100]; declares new_array to be an array of 100 pointers to double complex. That is not what you want. You merely want a pointer to double complex (which will point to the first element of an array that is provided by the function). The declaration for this is double complex *new_array;.
However, in array_function, you attempt to return array, where array is defined inside the function with double complex array[100];. That declaration, when used inside a function, declares an array that lasts only until the function returns. If you return its address (or the address of its first element), the pointer to that address will be invalid.
The proper way to return a new array from a function is to dynamically allocate the array, as with:
double complex *array = malloc(100 * sizeof *array);
if (!array)
{
fprintf(stderr, "Error, failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
… // Assign values to the array elements.
return array;
Then the caller is responsible for releasing the array at some later time, by passing the address to the free routine.
(To use malloc, free, and exit, add #include <stdlib.h> to your program.)
If you want to let the array_function create the content of new_array, you can send the array pointer as a parameter to the function, and let the function use that. You also need to change the definition of new_array to double complex new_array[100]
That is,
void array_function (double *a, double complex array[], int n)
{
int i;
for (i=0; i<n; i++)
{
array[i]=convert(*(a+i),i);
}
}
And in main():
double complex new_array[100];
...
array_function(array, new_array, N);
I created a vector struct and an addVector and subVector functions. I also created a print vector function.
I need to create 4 vector instances: two for input, two for output (one for the addition and one for the subtraction). I need to call printVector to print the result from addVector and the result from subVector. I think most of it is correct. I am just not sure what to do.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
double x;
double y;
double z;
} VECTOR;
VECTOR addVector(VECTOR *addOne, VECTOR *addTwo) {
double addX = addOne->x + addTwo->x;
double addY = addOne->y + addTwo->y;
double addZ = addOne->z + addTwo->z;
};
VECTOR subVector(VECTOR *subOne, VECTOR *subTwo){
double subX = subOne->x - subTwo->x;
double subY = subOne->y - subTwo->y;
double subZ = subOne->z - subTwo->z;
};
void printVector(VECTOR *printVector) {
printf("%lf, %lf, %lf\n", printVector->x, printVector->y, printVector->z);
};
void main() {
VECTOR A;
VECTOR B;
VECTOR C = addVector(&A, &B);
VECTOR D = subVector(&A, &B);
printf("Enter three doubles.\n");
scanf_s("%lf %lf %lf", &A.x, &A.y, &A.z);
addVector(&A, &B);
printVector(&C);
subVector(&A, &B);
printVector(&D);
system("pause");
};
You compute the values of the VECTOR coordinates in addVector and subVector, but you do not return a VECTOR structure.
Here is how to do it, and also note that since the VECTOR arguments are not modified, the pointers should be const qualified to underscore this property:
VECTOR addVector(const VECTOR *addOne, const VECTOR *addTwo) {
VECTOR add;
add.x = addOne->x + addTwo->x;
add.y = addOne->y + addTwo->y;
add.z = addOne->z + addTwo->z;
return add;
}
VECTOR subVector(const VECTOR *subOne, const VECTOR *subTwo) {
VECTOR sub;
sub.x = subOne->x - subTwo->x;
sub.y = subOne->y - subTwo->y;
sub.z = subOne->z - subTwo->z;
return sub;
}
void printVector(const VECTOR *printVector) {
printf("%lf, %lf, %lf\n", printVector->x, printVector->y, printVector->z);
}
In your main function, you use vectors A and B before initializing them or reading their values from the user. Modify the code this way:
void main() {
VECTOR A = { 0, 0, 0 };
VECTOR B = { 0, 0, 0 };
VECTOR C, D;
printf("Enter three doubles for A\n");
scanf_s("%lf %lf %lf", &A.x, &A.y, &A.z);
printf("Enter three doubles for B\n");
scanf_s("%lf %lf %lf", &B.x, &B.y, &B.z);
C = addVector(&A, &B);
printVector(&C);
D = subVector(&A, &B);
printVector(&D);
system("pause");
}
Finally, do not put a ; after the body of your functions.
Note also that you should enable all compiler warnings as it can help avoid silly bugs such as the above. Use gcc -Wall -W or clang -Weverything for command line compilers, and increase the warning level in the Visual Studio IDE if you use that.
addVector and subVector compute the components of the new vector, but don't actually return a new vector. But then, you call addVector and subVector and ignore the return value, so at least you are consistent.
I've been working through this problem, and I believe I have an error in where my pointers within my struct are pointing. However, I can't seem to figure out where I'm going wrong.
My code is meant to take in 2 complex numbers, then multiply and divide them, and then spit out both answers.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct complex_t
{
double real; // real part
double imag; // imaginary part
} complex_t;
// Multiplication Function //
void *multiply()
{
struct complex_t a, b, c;
c.real == ((a.real * b.real) - (a.imag * b.imag));
c.imag == ((a.imag * b.real) + (a.real * b.imag));
if ( c.imag >= 0 )
printf("Multiplication = %d + %di\n", c.real, c.imag); // Postive Imaginary case
else
printf("Multiplication = %d %di\n", c.real, c.imag); // Negative Imaginary case
}
// Division Function //
void *divide()
{
int numer1, numer2, denom;
struct complex_t a, b, c;
if ( b.real == 0 || b.imag == 0 ) // Case to Avoid Dividing by 0
printf("Division by 0 + 0i is not allowed.");
else
{
numer1 = ((a.real * b.real) + (a.imag * b.imag));
numer2 = ((a.imag * b.real) - (a.real * b.imag));
denom = ((b.real * b.real) + (b.imag * b.imag));
c.real == (numer1/denom);
c.imag == (numer2/denom);
if (numer2/denom >= 0)
printf("Division = %d + %di \n", c.real, c.imag); // Postive Imaginary case
else
printf("Division = %d %di \n", c.real, c.imag); // Negative imaginary case
}
}
// Main - to execute the two functions //
int main() {
struct complex_t a, b, c;
printf("Enter a and b where a + ib, for the first complex number.");
printf("\na = ");
scanf("%d", &a.real);
printf("b = ");
scanf("%d", &a.imag);
printf("Enter c and d where c + id, for the second complex number.");
printf("\nc = ");
scanf("%d", &b.real);
printf("d = ");
scanf("%d", &b.imag);
multiply();
divide();
return 0;
}
This is an example of what this program is producing:
Multiplication = 69144 -4196352i
Division = -13339222 0i
Any tips as to where I can start figuring this error out would be great.
C is an exact language. There is no such thing as syntax that is close enough. This is a great strength in C, but it is one hurdle beginning programmers have to come to terms with and understand before any real learning can take place. That includes understanding what each part of each line does, including the format strings. If you don't fully understand what each part of each line is doing -- look it up. Read the man pages, search for further information, until you do. It will save you a ton of time in the long run.
One of the things you can do that will, above all, help you find the problems in your code is to compile with Warnings enabled. That means including at least -Wall -Wextra in your compile string. For example, in your code, the screen was littered with warnings, including code with no apparent function and expected double but have int. Those things are telling you, you can try and run your code -- but DO NOT expect it to work right. You have to fix those, before you can have reasonable confidence that you will get more than garbage (or a crash) out of your code.
Another primary bit of learning that must take place is Always initialize your variables (to zero if nothing else). Attempting to access an uninitialized variable is Undefined Behavior. (it's anybody's guess what will happen.)
That being said. You had part of the code right. Your issues basically took slowing down, reading what the compiler was telling you was wrong, fixing it, and trying again. That's the key to C, slow down and get it right.
Enough blather -- are you going to help or not? Of course. Read through the following. Understand why the changes were necessary, and you will be able to consider it a good bit of learning for the day. However, the fixes in the code below, are not near as important as the guidance above for approaching C programming. (give a man a fish....):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
double real; // real part
double imag; // imaginary part
} complex_t;
// Multiplication Function //
void multiply (complex_t *a, complex_t *b, complex_t *c) {
/* struct complex_t a, b, c; */
c->real = ((a->real * b->real) - (a->imag * b->imag));
c->imag = ((a->imag * b->real) + (a->real * b->imag));
if (c->imag >= 0)
printf ("\nMultiplication = %f + %fi\n", c->real, c->imag); // Postive Imaginary case
else
printf ("\nMultiplication = %f %fi\n", c->real, c->imag); // Negative Imaginary case
}
// Division Function //
void divide (complex_t *a, complex_t *b, complex_t *c) {
int numer1, numer2, denom;
/* struct complex_t a, b, c; */
if (b->real == 0 || b->imag == 0) // Case to Avoid Dividing by 0
printf ("Division by 0 + 0i is not allowed.");
else {
numer1 = ((a->real * b->real) + (a->imag * b->imag));
numer2 = ((a->imag * b->real) - (a->real * b->imag));
denom = ((b->real * b->real) + (b->imag * b->imag));
c->real = (numer1 / denom);
c->imag = (numer2 / denom);
if (numer2 / denom >= 0)
printf ("\nDivision = %f + %fi \n", c->real, c->imag); // Postive Imaginary case
else
printf ("\nDivision = %f %fi \n", c->real, c->imag); // Negative imaginary case
}
}
// Main - to execute the two functions //
int main () {
complex_t a = { 0, 0 }, b = { 0, 0 }, c = { 0, 0 };
printf ("\nEnter a and b where a + ib, for the first complex number.\n\n");
printf (" a (a.real) = ");
scanf ("%lf", &a.real);
printf (" b (a.imag) = ");
scanf ("%lf", &a.imag);
printf ("\nEnter c and d where c + id, for the second complex number.\n\n");
printf (" c (b.real) = ");
scanf ("%lf", &b.real);
printf (" d (b.imag) = ");
scanf ("%lf", &b.imag);
multiply (&a, &b, &c);
divide (&a, &b, &c);
printf ("\n");
return 0;
}
output:
$ ./bin/divmult
Enter a and b where a + ib, for the first complex number.
a (a.real) = 10
b (a.imag) = 3
Enter c and d where c + id, for the second complex number.
c (b.real) = 5
d (b.imag) = 5
Multiplication = 35.000000 + 65.000000i
Division = 1.000000 + 0.000000i
void *multiply()
The values of struct variables a and b are not initialized within this function you should be passing the scanned values in main() to this function as well as divide()
There is no reason here I see why you are returning void *. Pass parameters by reference or by value.
Little bit of a 2 parter. First of all im trying to do this in all c. First of all I'll go ahead and post my program
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
#include <string.h>
double f(double x);
void Trap(double a, double b, int n, double* integral_p);
int main(int argc, char* argv[]) {
double integral=0.0; //Integral Result
double a=6, b=10; //Left and Right Points
int n; //Number of Trapezoids (Higher=more accurate)
int degree;
if (argc != 3) {
printf("Error: Invalid Command Line arguements, format:./trapezoid N filename");
exit(0);
}
n = atoi(argv[2]);
FILE *fp = fopen( argv[1], "r" );
# pragma omp parallel
Trap(a, b, n, &integral);
printf("With n = %d trapezoids....\n", n);
printf("of the integral from %f to %f = %.15e\n",a, b, integral);
return 0;
}
double f(double x) {
double return_val;
return_val = pow(3.0*x,5)+pow(2.5*x,4)+pow(-1.5*x,3)+pow(0*x,2)+pow(1.7*x,1)+4;
return return_val;
}
void Trap(double a, double b, int n, double* integral_p) {
double h, x, my_integral;
double local_a, local_b;
int i, local_n;
int my_rank = omp_get_thread_num();
int thread_count = omp_get_num_threads();
h = (b-a)/n;
local_n = n/thread_count;
local_a = a + my_rank*local_n*h;
local_b = local_a + local_n*h;
my_integral = (f(local_a) + f(local_b))/2.0;
for (i = 1; i <= local_n-1; i++) {
x = local_a + i*h;
my_integral += f(x);
}
my_integral = my_integral*h;
# pragma omp critical
*integral_p += my_integral;
}
As you can see, it calculates trapezoidal rule given an interval.
First of all it DOES work, if you hardcode the values and the function. But I need to read from a file in the format of
5
3.0 2.5 -1.5 0.0 1.7 4.0
6 10
Which means:
It is of degree 5 (no more than 50 ever)
3.0x^5 +2.5x^4 −1.5x^3 +1.7x+4 is the polynomial (we skip ^2 since it's 0)
and the Interval is from 6 to 10
My main concern is the f(x) function which I have hardcoded. I have NO IDEA how to make it take up to 50 besides literally typing out 50 POWS and reading in the values to see what they could be.......Anyone else have any ideas perhaps?
Also what would be the best way to read in the file? fgetc? Im not really sure when it comes to reading in C input (especially since everything i read in is an INT, is there some way to convert them?)
For a large degree polynomial, would something like this work?
double f(double x, double coeff[], int nCoeff)
{
double return_val = 0.0;
int exponent = nCoeff-1;
int i;
for(i=0; i<nCoeff-1; ++i, --exponent)
{
return_val = pow(coeff[i]*x, exponent) + return_val;
}
/* add on the final constant, 4, in our example */
return return_val + coeff[nCoeff-1];
}
In your example, you would call it like:
sampleCall()
{
double coefficients[] = {3.0, 2.5, -1.5, 0, 1.7, 4};
/* This expresses 3x^5 + 2.5x^4 + (-1.5x)^3 + 0x^2 + 1.7x + 4 */
my_integral = f(x, coefficients, 6);
}
By passing an array of coefficients (the exponents are assumed), you don't have to deal with variadic arguments. The hardest part is constructing the array, and that is pretty simple.
It should go without saying, if you put the coefficients array and number-of-coefficients into global variables, then the signature of f(x) doesn't need to change:
double f(double x)
{
// access glbl_coeff and glbl_NumOfCoeffs, instead of parameters
}
For you f() function consider making it variadic (varargs is another name)
http://www.gnu.org/s/libc/manual/html_node/Variadic-Functions.html
This way you could pass the function 1 arg telling it how many "pows" you want, with each susequent argument being a double value. Is this what you are asking for with the f() function part of your question?