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]);
}
Related
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);
}
I have to use:
float average(const int tab[], int size);
float stdDev(const int tab[], int size);
to printf average and stdDev in C.
I have problem with average and i think with const int.
When i add const int tab[101] i have error with a1;
So how can i make it work with const int (if i can).
And if it is anything wrong with this code.
Any help will be helpful.
#include<stdio.h>
#include<math.h>
float average(const int tab[], int size);
float stdDev(const int tab[], int size);
int main()
{
float ave, std;
int a1;
int j;
int tab[101];
printf("Podaj liczby: ");
for(j=0; j<=99; j++)
{
a1 = scanf("%d", &tab[j]);
if(a1<1)
{
printf("Incorrect input");
return 1;
}
if(tab[0]==0)
{
printf("not enough data available");
return 2;
}
if(tab[j]==0)
{
break;
}
}
ave = average(tab, j);
printf("%.2f\n", ave);
std = stdDev(tab, j);
printf("%.2f", std);
return 0;
}
float average(const int tab[], int size)
{
int i;
float y=0, x;
if(size<=0)
{
return -1;
}
for(i=0; i<size; i++)
{
x = x + tab[i];
}
y = x/size;
return y;
}
float stdDev(const int tab[], int size)
{
int i;
float y, z, z1, z2=0, z3=0;
if(size<=0)
{
return -1;
}
y = average(tab, size);
for(i=0; i<size; i++)
{
z = tab[i] - y;
z1 = pow(z, 2);
z2 = z2 + z1;
z=0;
z1=0;
}
z3 = sqrt(z2/size);
return z3;
}
You define the variable x in average here:
float y=0, x;
without giving it a value. Then here:
x = x + tab[i];
you are reading its value without setting it anywhere beforehand. Because you never gave x a value, its value will be indeterminate and reading it will cause undefined behavior, which means that your program could e.g. print garbage output.
Always initialize your variables:
float y=0, x=0;
i know there are similiar questions but i tried the suggestions there and it still does not work, here my complete code;
#include <stdio.h>
#include <math.h>
void ludec(int N, double lu[N][N]){
double temp;
int k,i,j;
for(k=0;k<N;k++){
for(i=k+1;i<N;i++){
temp=lu[i][k]/=lu[k][k];
for(j=k+1;j<N;j++){
lu[i][j]-=temp*lu[k][j];
}
}
}
}
void matmul(int u,int m,int n,double p[u][m],double bb[m][n]){
double mul[u][n];
int ii,jj,kk;
for(ii=0;ii<u;ii++){
for(jj=0;jj<n;jj++){
mul[ii][jj]=0.0;
}
}
for(ii=0;ii<u;ii++){
for(jj=0;jj<n;jj++){
for(kk=0;kk<m;kk++){
mul[ii][jj]=mul[ii][jj]+p[ii][kk]*bb[kk][jj];
printf("la %f ii %d jj%d kk%d\n",mul[ii][jj],ii,jj,kk);
}
}
}
}
int main(void){
double lu[3][3]={{4.0,3.0,-2.0},{-1.0,-1.0,3.0},{2.0,-1.0,5.0}};
double a[3][3]={{4.0,3.0,-2.0},{-1.0,-1.0,3.0},{2.0,-1.0,5.0}};
double y[3][1];
double b[3][1]={{9.0},{-4.0},{6.0}};
double x[3][1];
int i,j,N=3;
double f=0;
ludec(N, lu);
y[0][0]=b[0][0];
for(i=1;i<3;i++){
for(j=0;j<i;j++){
f+=lu[i][j]*y[j][0];
}
y[i][0]=(b[i][0]-f);
f=0;
}
f=0;
x[2][0]=y[2][0]/lu[2][2];
for(i=1;i>=0;i--){
for(j=1+i;j<3;j++){
f+=lu[i][j]*x[j][0];
}
x[i][0]=(y[i][0]-f)/lu[i][i];
f=0;
}
printf("%f\n %f\n %f\n",x[0][0],x[1][0],x[2][0]);
for(i=0;i<3;i++){
for(j=0;j<3;j++){
printf("%f %d %d\n",lu[i][j],i,j);
}
}
double mul[3][1];
matmul(3,3,1,a,x);
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%f %d %d\n",mul[i][j],i,j);
}
}
return 0.0;
}
here is the part responsible by multiplication;
the problem is
i have to get 3*1 matrix as result in matrix multiplication, but it gives bigger matrix with alot of garbage elements i monitor the matrix multiplication by printf in the matmul function and it seems to work but when i do same out side the matmul function it gives garbage only some values are correct with a lot of useless wrong elements.
void matmul(int u,int m,int n,double p[u][m],double bb[m][n]){
double mul[u][n];
int ii,jj,kk;
for(ii=0;ii<u;ii++){
for(jj=0;jj<n;jj++){
mul[ii][jj]=0.0;
}
}
for(ii=0;ii<u;ii++){
for(jj=0;jj<n;jj++){
for(kk=0;kk<m;kk++){
mul[ii][jj]=mul[ii][jj]+p[ii][kk]*bb[kk][jj];
printf("la %f ii %d jj%d kk%d\n",mul[ii][jj],ii,jj,kk);
}
}
}
}
the problem is matmul function and i dont know why it does not work i already initialized the matrix with zeros. am i using void function property wrong?
i am very new to c hence there may be something i am doing wrong. the overall code is for lu decompositation, and i want to see wheter the code works or not by multiplying result with initial matrix.
this is the out put
mul is a local variable in matmul, thus the result is not visible to the calling function. You should modify the matmul function to take the result matrix as an argument:
void matmul(int u, int m, int n,
double mul[u][n], const double p[u][m], const double bb[m][n])
{
for (int i = 0; i < u; i++) {
for (int j = 0; j < n; j++) {
mul[i][j] = 0.0;
for (int k = 0; k < m; k++) {
mul[i][j] += p[i][k] * bb[k][j];
}
}
}
}
Invoke from main as
double mul[3][1];
matmul(3, 3, 1, mul, a, x);
And print the output vector:
for (i = 0; i < 3; i++) {
for (j = 0; j < 1; j++) {
printf("%f %d %d\n", mul[i][j], i, j);
}
}
I'm just started learning C programming. So I have problem with change temperature via Functions. Please check this program and where did I do mistake? Thank you!!!
#include<stdio.h>
double f_to_c(double f);
double get_integer(void);
int main(void)
{
double a;
a = get_integer();
printf("he degree in C:%f", f_to_c(a));
return 0;
}
double get_integer(void)
{
double n;
printf("Enter the variable:");
scanf_s("%f", &n);
return n;
}
double f_to_c(double f)
{
int f, c;
c = 5.0 / 0.9*(f - 32.0);
return c;
}
`
In your case,
double f_to_c(double f)
{
int f, c;
c = 5.0 / 0.9*(f - 32.0);
return c;
}
int f is shadowing the double f. Use some other name for the variable(s).
Essentially, you're trying to make use of an uninitialized automatic local variable which invokes undefined behavior
Corrected code below:
#include<stdio.h>
double f_to_c(double f);
double get_integer(void);
int main(void)
{
double a;
a = get_integer();
printf("he degree in C:%lf\n", f_to_c(a));
return 0;
}
double get_integer(void)
{
double n;
printf("Enter the variable:");
scanf("%lf", &n);
return n;
}
double f_to_c(double f)
{
double c;
c = 5.0/9*(f-32);
return c;
}
As you can see:
Type of c variable in f_to_c is changed to double, because of you need a double return for that function
Formula to convert F to C was not correct.
Format specifier of your printf and scanf was not correct.
in get_integer function return type is double, instead it should be integer
int get_integer(void)
{
int n;
printf("Enter the variable:");
scanf_s("%d", &n);
return n;
}
in your other function f_to_c, return type is double but you're returning an integer
double f_to_c(double f)
{
int f;
double c;
c = (5.0 / 0.9)*(f - 32.0);
return c;
}
also at the start, you need to change your code to:
int main(void)
{
int a;
a = get_integer();
printf("he degree in C:%f", f_to_c(a));
return 0;
}
I'm trying to calculate sin and cos without using math library with taylor series witch is
sinx =∑n=0 to n=∞ (-1)^n * x^(2n+1) / (2n+1)! and this code produces whatever the input is 0,00000 for sin 1,00000 for cos where is the problem in this code
#include <stdio.h>
#include <stdlib.h>
double fakt(int);
double power(int,int);
int negative_positive(int);
double calculate_sin(int,int);
double calculate_cos(int,int);
double calculate_radyan(int);
int main() {
int degree,number;
char command;
do{
scanf("%c",&command);
if(command=='d' || command=='D'){
scanf("%d %d",°ree,&number);
double radyan = calculate_radyan(degree);
printf("%lf \n%lf ",calculate_sin(radyan,number),calculate_cos(radyan,number));
}
}while(command!='e' && command!='E');
return 0;
}
double fakt(int n){
int i;
double result=1;
for(i=1;i<n;i++)
result = result*i;
return result;
}
double power(int base, int exponent){
int i;
double result=1;
for(i=0;i<exponent;i++)
result = result*base;
return result;
}
int negative_positive(int number){
if(number % 2 == 0)
return 1;
else
return -1;
}
double calculate_sin(int degree , int n){
int i;
double result=0;
double tmp=0;
for(i=0;i<n;i++){
tmp=negative_positive(i)*power(degree,2*i+1)/fakt(2*i+1);
result=tmp+result;}
return result;
}
double calculate_cos(int degree , int n){
int i;
double result=0;
double tmp=0;
for(i=0;i<n;i++)
{
tmp=negative_positive(i)*power(degree,i*2)/fakt(2*i);
result=tmp+result;
}
return result;
}
double calculate_radyan(int degree){
double result,pi=3.14159;
result =pi/180*degree;
return result;
}
ı will answer my own question but ı found the solution. when program trys to go to power method with double radyan variable it converts that variable to 0 cause that method just takes integer variables power(double base,int exponent) is solved my problem