Perimeter calculation in C - c

I'm trying to use the distance between points formula to calculate the perimeter of any geometric figure, but the function is not delivering the values it should. I have no clue of what I'm doing wrong
#include <math.h>
int perimeter(int flag, dot d[]){
float result, sum1, sum2, sum3, quad1, quad2, op[flag], sum;
for(int c=0;c<flag;c++){
sum1=d[c+1].x-d[c].x;
sum2=d[c+1].y-d[c].y;
quad1=pow(sum1, 2);
quad2=pow(sum2, 2);
sum3=quad1+quad2;
result=sqrt(sum3);
op[c]=result;
}
for(int c=0;c<flag;c++){
sum+=op[c];
}return sum;
}
Test values:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct dot{
float x,y;
}dot;
int main(){
int flag=4;
dot d[flag];
d[0].x=9;
d[0].y=10;
d[1].x=21;
d[1].y=10;
d[2].x=21;
d[2].y=16;
d[3].x=9;
d[4].y=16;
float result, sum1, sum2, sum3, quad1, quad2, op[flag], sum=0.0;
for(int c=0;c<flag;c++){
sum1=d[c+1%flag].x-d[c].x;
sum2=d[c+1%flag].y-d[c].y;
quad1=pow(sum1, 2);
quad2=pow(sum2, 2);
sum3=quad1+quad2;
result=sqrt(sum3);
printf("distance %d: %d\n", c, result);
sum+=result;
}
printf("final result: %d\n", result);
}
Console log(printing steps):
gcc version 4.6.3
distance 0: 0
distance 1: 1
distance 2: 2
distance 3: 3
final result: 26533904

You should look up the hypot() functions declared in the <math.h> header. You could end up with:
float perimeter(int n_dots, dot d[])
{
float sum = 0.0;
for (int i = 0; i < n_dots; i++)
{
int n = (i+1) % n_dots;
sum += hypotf(d[n].x - d[i].x, d[n].y - d[i].y);
}
return sum;
}
If you need to report on the values calculated, you can capture the result of hypotf() before you add it to sum.
Note, too, that you should return a float value. In my book, you should change float to double throughout (and use hypot() in place of hypotf()), but that's somewhat separate as an issue. Returning float (or double) rather than int is rather important, I think.
The MCVE (Minimal, Complete, Verifiable Example) version of your code might be:
#include <math.h>
#include <stdio.h>
typedef struct dot
{
float x, y;
} dot;
float perimeter(int n_dots, dot d[]);
int main(void)
{
enum { num_dots = 4 };
dot d[num_dots] =
{
{ .x = 9, .y = 10 },
{ .x = 21, .y = 10 },
{ .x = 21, .y = 16 },
{ .x = 9, .y = 16 },
};
printf("Perimeter: %.3f\n", perimeter(num_dots, d));
return 0;
}
float perimeter(int n_dots, dot d[])
{
float sum = 0.0;
for (int i = 0; i < n_dots; i++)
{
int n = (i + 1) % n_dots;
sum += hypotf(d[n].x - d[i].x, d[n].y - d[i].y);
}
return sum;
}
Using a VLA prevents you using an initializer for it, so I made the array into a regular fixed size array.
Output:
Perimeter: 36.000
For the given data, this is correct (the four sides are of length 12, 6, 12, 6).

Initialize sum with 0.0.
Then
Replace
op[c]=result;
with
sum+=result;
You don't need the other for loop.
Secondly, make sure the value of the variable flag passed to the perimeter function is 1 less than the size of the dots array d.
Lastly, you need to add the distance between the last point and the first point to the sum. (After the for loop).
sum1 = d[flag+1].x - d[0].x;
sum2 = d[flag+1].y - d[0].y;
quad1=pow(sum1, 2);
quad2=pow(sum2, 2);
sum3=quad1+quad2;
result=sqrt(sum3);
sum+=result;

Here is my version, with better variable names,
#include <math.h>
float perimeter(int flag, dot d[]){
float sum_x, sum_y, quad_x, quad_y, sum = 0;
for(int c=0;c<flag;c++){
sum_x=d[(c+1) % flag].x-d[c].x;
sum_y=d[(c+1) % flag].y-d[c].y;
quad_x=pow(sum_x, 2);
quad_y=pow(sum_y, 2);
sum += sqrt(quad_x + quad_y);
}
return sum;
}

Related

Write a C function to evaluate the series // sin(x) = x-(x3 /3!)+(x5 /5!)-(x7 /7!)+... // up to 10 terms

#include <stdio.h>
#include<math.h>
int series(float,float);
int main()
{
float x,n,series_value;
printf("Enter the value of x: ");
scanf("%f",&x);
printf("\nEnter the value of n: ");
scanf("%f",&n);
series_value=series(x,n);
printf("\nValue of series sin (%.2f) is: %f\n",x,series_value);
return 0;
}
int series(float x,float n)
{
int i,sum=0,sign=-1;
int j,fact=1,p=1;
for (i=1; i<=(2*n)-1; i+=2)
{
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
sign=-1*sign;
sum=sum + sign*p/fact;
}
return (sum);
}
Output:
Enter the value of x: 5
Enter the value of n: 10
(lldb)
and this message
Thread 1: EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
![Thread 1 Queue : com.apple.main-thread (serial)
]1
Why is this message coming? and what is wrong in the program as answer is not coming right
There is a few problems with your code. As #PaulHankin said, when fact overflows and becoms zero, you will have a division by zero, and "weird things" happen.
Your factorial and power calculation is also wrong. You are recalculating it in each iteration of the outer loop without reseting fact and p first:
fact = 1; // You need to reset fact and p to its start value here
p = 1;
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
Your third problem is that for your function calculate the correct value for sin, which is not an integer value, you need to use float, or even better double, when calculating sum. So sum must be declared float, and the division p/fact must use float division. By also declaring p and fact as float, you will solve both the overflow issue, and use the correct division. Naturally your function must also return a float
float series(float x,float n)
{
int i,sign=-1;
int j,
float sum = 0;
float fact = 1;
float p = 1;
for (i=1; i<=(2*n)-1; i+=2)
{
fact = 1;
p = 1;
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
sign=-1*sign;
sum=sum + sign*p/fact;
}
return (sum);
}
This code still has a minor problem. By having an inner loop, it is slower than necessary. Since this probably is homework, I am not getting rid of that loop for you, just giving you a hint: You don't have to recalculate fact from scratch on each iteration of the outer loop, just try to find out how fact changes from one iteration to the next. The same goes for p.
//Series of Sinx
#include<stdio.h>
#include<math.h>
#define ACCURACY 0.0001
int factorial(int n);
int main()
{
float x,sum,term;
int i,power;
printf("Enter value of X: ");
scanf("%f",&x);
i=1;
power=3;
sum=x;
term=x;
while(term>=ACCURACY)
{
term = pow(x,power) / factorial(power);
if(i%2==1)
{
sum -= term;
}
else
{
sum += term;
}
power+=2;
i++;
}
printf("sin(%f) = %.6f\n",x,sum);
return 0;
}
int factorial(int n){
int i=n,fact=1;
for(i=1;i<=n;i++)
{
fact=fact*i;
}
return fact;
}
plenty bugs. To do not caclulate the fact values all the time they are in the lookup table
#include <stdio.h>
#include <math.h>
double series(double,int);
long long fact[] = { 1, 2, 6, 24,
120, 720, 5040, 40320,
362880, 3628800, 39916800, 479001600,
6227020800, 87178291200, };
double mypow(double x, unsigned p)
{
double result = x;
while(p && --p)
result *= x;
return result;
}
int main()
{
for(double x = 0; x <= M_PI + M_PI / 60; x += M_PI / 30)
printf("Value of series sin (%.2f) is: %f\n",x,series(x, 5));
fflush(stdout);
}
double series(double x,int n)
{
double sum = x;
int i,sign=1;
for (i=3; i<=(2*n)-1; i+=2)
{
sign=-1*sign;
sum += sign*(mypow(x, i)/fact[i -1]);
}
return (sum);
}
https://godbolt.org/z/U6dULN
maybe its due to floating-point exception as u have declared that the function should return int type value
int series(float,float);//hear
so u can try editing the return type of this function as float
Note:-also u need to change at function definition and the datatype of
int i,sum=0,sign=-1;
int j,fact=1,p=1;
to float as it is returning the value (sum) which should also be float

Trying to Approximate Euler's number in C

I am trying to approximate Euler's number using the formula (1+(1/n))^n.
The compiler is telling me that there is an "expected expression before 'double'"
Here is the code:
#include <stdio.h>
#include <math.h>
int main()
{
int x, y, power;
int num = 1;
int position = 1;
while (position <= 100)
{
num = 1/num;
num = num + 1;
x = num;
power = double pow(x, x); //here
printf("%f", power);
position += 1;
num = position;
}
}
If you want a number to be a double (number with decimals), you need to define it as a double, not an integer. I have this code which should solve your problem. Also make sure to compile gcc FILEPATH -lm -o OUTPUTPATH if you are using UNIX.
#include <stdio.h>
#include <math.h>
int main()
{
double x, y, power, num = 1; //doubles allow for decimal places so declare it as double
int position = 1; //Position seems to only be an integer, so declare it as an int.
while (position <= 100)
{
num = 1/num;
num++;
x = num;
power = pow(x, x);
printf("%f", power);
position += 1;
num = position;
}
}
Another option is a for loop:
#include <stdio.h>
#include <math.h>
int main()
{
double x, y, power, num = 1;
for (int i = 1; i <= 100; i++) {
num = 1/num;
num = num + 1;
x = num;
power = pow(x, x);
printf("%f", power);
position += 1;
num = i;
}
}
If you are trying to approximate Euler's number, I don't see why not just try something like:
static const double E = 2.718281828459045;
I have simply corrected syntax errors in your program, but I don't think it will actually get you E. See this page about calculating E in C.
I'm no C master but isnt just calling double by itself a type declaration and not type casting? wouldnt it be power = (double) pow(x, x); if you are type casting? see: https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
I reworked some mistakes in your code and think it should work now; however, the style, which I kept untouched, is confusing.
#include <stdio.h>
#include <math.h>
int main()
{
double power; //stores floating point numbers!
double num = 1;//stores floating point numbers!
int position = 1;
while (position <= 100)
{
num = 1/num;
num = num + 1;
power = pow(num, position); //x not needed, this is what you ment
printf("%f\n", power); //%d outputs decimal numbers, f is for floats
position += 1;
num = position;
}
}
To improve your code, I would suggest to simplify it. Something along the lines of this
#include <stdio.h>
#include <math.h>
int main()
{
double approx;
for(int iter=1; iter<=100; iter++){
approx=pow((1+1./iter),iter);
printf("%f\n", approx);
}
}
is much easier to understand.

returning a value from a two arrays and a count integer C language

int main()
{
double dUnitPriceM[]={19.99, 50.50, 2.10};
long lOrderQuantityM[] = {10, 2, 4};
int iItemCount = 3;
double dTotalCost;
dTotalCost = calculateTotalCost(dUnitPriceM, lOrderQuantityM, iItemCount);
printf("Total cost is %10.2lf\n", dTotalCost);
}
// code for calculateTotalCost function ??
double calculateTotalCost(double dUnitPriceM[], long lQuantityM[],
int iItemCount)
{
}
I am a beginner for coding C language and I am having trouble understanding how to use Arrays. I came up with the logic of creating a pseudocode but I cant code it.
All I know is that I have to start from the value of i =1; as i <= Item count, i++.
then assign i the result of the UnitPriceM[0] * QuantityM[0], increment them to the next array until it has reached its last value. Then sum the total of all the i's for example if i1= 100 + i2 = 120 + i3 =45 return them as the total cost.
#include <stdio.h>
double calculateTotalCost(double unitPrice[], long quantity[],int itemCount){
int i;
double totalCost=0.0;
for(i=0;i<itemCount;i++){
totalCost +=unitPrice[i] * quantity[i];
}
return totalCost;
}
void main() {
int i;
double dUnitPriceM[]={19.99, 50.50, 2.10};
long lOrderQuantityM[] = {10, 2, 4};
int iItemCount = 3;
double totalCost =0.0;
totalCost= calculateTotalCost(dUnitPriceM, lOrderQuantityM, iItemCount);
printf("Total cost is %f ", totalCost);
}
Here it is the basic logic of looping through all and doing the operation required.
double calculateTotalCost(double dUnitPriceM[], long lQuantityM[],
int iItemCount)
{
double sum=0;
for(int i=0;i<iItemCount;i++)
{
sum=sum+dUnitPriceM[i]*lQuantityM[i];
}
return sum;
}

C File Input/Trapezoid Rule Program

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?

Selecting and analysing window of points in an array

Could someone please advise me on how to resolve this problem.
I have a function which performs a simple regression analysis on a sets of point contained in an array.
I have one array (pval) which contains all the data I want to perform regression analysis on.
This is how I want to implement this.
I get an average value for the first 7 elements of the array. This is what I call a 'ref_avg' in the programme.
I want to perform a regression analysis for every five elements of the array taking the first element of this array as the 'ref_avg'. That is in every step of the regression analysis I will have 6 points in the array.
e.g
For the 1st step the ref_avg as calculated below is 70.78. So the 1st step in the simple regression will contain these points
1st = {70.78,76.26,69.17,68.68,71.49,73.08},
The second step will contain the ref_avg as the 1st element and other elements starting from the second element in the original array
2nd = {70.78,69.17,68.68,71.49,73.08,72.99},
3rd = {70.78,68.68,71.49,73.08,72.99,70.36},
4th = {70.78,71.49,73.08,72.99,70.36,57.82} and so on until the end.
The regression function is also shown below.
I don't understand why the first 3 elements of the 'calcul' array have value 0.00 on the first step of the regression, 2 elements on the 2nd step,1 elements on the 3rd.
Also the last step of the regression function is printed 3 times.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
float pval[]={76.26,69.17,68.68,71.49,73.08,72.99,70.36,57.82,58.98,69.71,70.43,77.53,80.77,70.30,70.5,70.79,75.58,76.88,80.20,77.69,80.80,70.5,85.27,75.25};
int count,Nhour;
const int MAX_HOUR = 24;
float *calcul=NULL;
float *tab_time =NULL;
float ref_avg;
int size_hour=7;
float sum=0;
int length = Nhour+1;
float m;
float b;
calcul=(float*)calloc(MAX_HOUR,sizeof(calcul));
if (calcul==NULL)
{
printf(" error in buffer\n");
exit(EXIT_FAILURE);
}
tab_time= calloc(MAX_HOUR,sizeof(float));
/* Get the average of the first seven elements */
int i;
for (i=0;i<size_hour;i++)
{
sum += pval[i];
}
ref_avg = sum / size_hour;
count=0;
/* perform the regression analysis on 5 hours increment */
while(count<=MAX_HOUR)
{
++count;
Nhour=5;
int pass = -(Nhour-1);
int i=0;
for(i=0;i<Nhour+1;i++)
{
if(count<MAX_HOUR)
{
calcul[0]=ref_avg;
calcul[i] =pval[count+pass];
pass++;
}
printf("calc=%.2f\n",calcul[i]); // For debug only
tab_time[i]=i+1;
if(i==Nhour)
{
linear_regression(tab_time, calcul, length, &m, &b);
printf("Slope= %.2f\n", m);
}
}
}
free(calcul);
calcul=NULL;
free(tab_time);
tab_time=NULL;
return 0;
}
/* end of the main function */
/* This function is used to calculate the linear
regression as it was called above in the main function.
It compiles and runs very well, was just included for the
compilation and execution of the main function above where I have a problem. */
int linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx = 0,
sumy = 0,
sumx2 = 0,
sumxy = 0;
int i;
if (n <= 1) {
*beta1 = 0;
*beta0= 0;
printf("Not enough data for regression \n");
}
else
{
float variance;
for (i = 0; i < n; i++)
{
sumx += x[i];
sumy += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
variance = (sumx2 - ((sumx * sumx) / n));
if ( variance != 0) {
*beta1 = (sumxy - ((sumx * sumy) / n)) / variance;
*beta0 = (sumy - ((*beta1) * sumx)) / n;
}
else
{
*beta1 = 0;
*beta0 = 0;
}
}
return 0;
}
I think this code produces sane answers. The reference average quoted in the question seems to be wrong. The memory allocation is not needed. The value of MAX_HOUR was 24 but there were only 23 data values in the array. The indexing in building up the array to be regressed was bogus, referencing negative indexes in the pval array (and hence leading to erroneous results). The variable Nhour was referenced before it was initialized; the variable length was not correctly set. There wasn't good diagnostic printing.
The body of main() here is substantially rewritten; the editing on linear_regression() is much more nearly minimal. The code is more consistently laid out and white space has been used to make it easier to read. This version terminates the regression when there is no longer enough data left to fill the array with 5 values - it is not clear what the intended termination condition was.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void linear_regression(const float *x, const float *y, const int n,
float *beta1, float *beta0);
int main(void)
{
float pval[]={
76.26, 68.68, 71.49, 73.08, 72.99, 70.36, 57.82, 58.98,
69.71, 70.43, 77.53, 80.77, 70.30, 70.50, 70.79, 75.58,
76.88, 80.20, 77.69, 80.80, 70.50, 85.27, 75.25,
};
const int Nhour = 5;
const int MAX_HOUR = sizeof(pval)/sizeof(pval[0]);
const int size_hour = 7;
float ref_avg;
float sum = 0.0;
float m;
float b;
float calc_y[6];
float calc_x[6];
/* Get the average of the first seven elements */
for (int i = 0; i < size_hour; i++)
sum += pval[i];
ref_avg = sum / size_hour;
printf("ref avg = %5.2f\n", ref_avg); // JL
/* perform the regression analysis on 5 hours increment */
for (int pass = 0; pass <= MAX_HOUR - Nhour; pass++) // JL
{
calc_y[0] = ref_avg;
calc_x[0] = pass + 1;
printf("pass %d\ncalc_y[0] = %5.2f, calc_x[0] = %5.2f\n",
pass, calc_y[0], calc_x[0]);
for (int i = 1; i <= Nhour; i++)
{
int n = pass + i - 1;
calc_y[i] = pval[n];
calc_x[i] = pass + i + 1;
printf("calc_y[%d] = %5.2f, calc_x[%d] = %5.2f, n = %2d\n",
i, calc_y[i], i, calc_x[i], n);
}
linear_regression(calc_x, calc_y, Nhour+1, &m, &b);
printf("Slope= %5.2f, intercept = %5.2f\n", m, b);
}
return 0;
}
void linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx1 = 0.0;
float sumy1 = 0.0;
float sumx2 = 0.0;
float sumxy = 0.0;
assert(n > 1);
for (int i = 0; i < n; i++)
{
sumx1 += x[i];
sumy1 += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
float variance = (sumx2 - ((sumx1 * sumx1) / n));
if (variance != 0.0)
{
*beta1 = (sumxy - ((sumx1 * sumy1) / n)) / variance;
*beta0 = (sumy1 - ((*beta1) * sumx1)) / n;
}
else
{
*beta1 = 0.0;
*beta0 = 0.0;
}
}

Resources