I have been cracking my head at achieving something very simple in C in order to make my one of the programs (not written by me) in our computational physics project more dynamic: comparing two different arrays element by element in an if conditional.
#include <math.h>
#include <stdio.h>
#include "header.h"
const int nParam = 10;
double a[nParam], a_tmp[nParam];
double values[10000];
double FitParam(double x){
int xindex;
double value;
xindex=(int) x;
if (a_tmp[1]==a[1] && a_tmp[2]==a[2] && a_tmp[3]==a[3] && a_tmp[4]==a[4]){
value=values[xindex];
return(value);
}
// code continues... (very long subroutine and there is recursion for
// the subroutine so this if statement above is very important).
The array a[ ]
has a varying number of significant elements every time we run our program; for example, right now, we are using this subroutine for only elements [1]
through [4]
. However, in other cases, we will want to have fewer or more elements, say, up to 3 elements or up to 5 elements, respectively.
So essentially, I want to be able to rewrite the if statement above so that it is dynamic... in other words, if there are N elements considered, then it will do:
if (a_tmp[1]==a[1] && ... && a_tmp[N]==a[N]){}
So this if conditional should vary whenever our number N of elements of interest is changed (N is defined as a #define in the header of this file, which I just named header.h).
I would greatly appreciate your support on this task. Thank you.
Your best bet is to rewrite it as a function that returns true or false (1 or 0):
int compareArrays(double a[], double b[], int n) {
int ii;
for(ii = 1; ii <= n; ii++) {
if (a[ii] != b[ii]) return 0;
// better:
// if(fabs(a[ii]-b[ii]) < 1e-10 * (fabs(a[ii]) + fabs(b[ii]))) {
// with the appropriate tolerance
}
return 1;
}
Note that it is usually bad practice to compare doubles for equality - you are better off comparing their difference, and making sure the absolute value is less than some tolerance.
Also note you are comparing elements 1 through n - C arrays start at 0 though.
You would use the above with
if (compareArrays(a, a_tmp, N)) {
where the value N
is #define
'd per your question.
If you want to be "clever" and avoid a loop, you can write the following - it will stop ("short-circuiting") as soon as you reach the right number of comparisons. It is still a Bad Idea to compare doubles for equality but I will leave that for another time (see comment in code above for a solution).
if(a[1]==a_temp[1] && (2 > N || (a[2]==a_temp[2] && (3 > N || (a[3]==a_temp[3]))))) {
This makes the "and the rest" true
as soon as you have compared the right number of terms - so it will stop evaluating terms (as you need). I am not convinced this is either faster, or better code - but it is "dynamic"... You can obviously make this expression as long as you would like; I just wrote the first three terms so you get the idea. I DO NOT RECOMMEND IT.
As for the comparison of doubles, you might consider replacing
if(a == b)
with
if(closeEnough(a, b))
where you define the macro
#define closeEnough(a, b) (fabs((a)-(b)) < 1e-10 * (fabs(a) + fabs(b)))? 1 : 0
This will make sure that your doubles don't have to be "exactly equal" - depending on how you arrived at them, they will almost never be, and the relative tolerance of 1 part in 10^10 is usually plenty for most practical comparisons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With