Reputation: 103
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.
Upvotes: 10
Views: 93160
Reputation: 1
This one, lets you compare two arrays of any type and will return the index of the first unequal elements found. If the arrays are identical the returned value will be the number of elements in the array.
int compareArrays(void* arrayA, void* arrayB, uint numElements, uint elementSizeBytes) {
//returns -1 on error, numElememts if the arrays are equal or the index
//of the first unequal elements
uint i;
uint8_t* byteArrayA;
uint8_t* byteArrayB;
if(elementSizeBytes < 1) {
return -1;
}
if(numElements < 1) {
return -1;
}
byteArrayA = (uint8_t*) arrayA;
byteArrayB = (uint8_t*) arrayB;
for(i = 0; i < (numElements*elementSizeBytes); i++) {
if(byteArrayA[i] != byteArrayB[i]) {
break;
}
}
return i / elementSizeBytes;
}
An example call:
uint16_t test1[6] = {12, 15, 24, 86, 92, 15};
uint16_t test2[6] = {12, 15, 24, 86, 93, 15};
int retVal = compareArrays(test1, test2, 6, 2);
Upvotes: 0
Reputation: 9845
A simple implementation is a linear comparison between both arrays, it just iterate over the array length and check if (a[i] != b[i])
, if so return false
& break out of the iteration.
See the example below:
#include <stdio.h>
int compareArrays(int a[], int b[], int n)
{
for (int i=0; i<n; ++i)
{
if (a[i] != b[i])
{
return -1;
}
}
return 0;
}
int main()
{
int arr1[4] = {3, 4, 5, 7};
int arr2[4] = {3, 4, 5, 7};
int arr3[4] = {1, 5, 3, 7};
int arr4[4] = {3, 4, 5, 19};
printf("Should be True %d\n", compareArrays(arr1, arr2, 4));
printf("Should be False %d\n", compareArrays(arr3, arr4, 4));
return 0;
}
You should get:
Should be True 0
Should be False -1
Run it online this example: https://repl.it/@abranhe/compare-arrays-in-c
Upvotes: 1
Reputation: 6602
If it must be at compile time, there is nothing in the standard that provides for a repeating macro like that. As in another (question), for bounded N, you can prepare N macros that expand to your desired comparison.
While yet another alternative is memcmp
memcmp( data, data2, array_len_in_bytes );
Upvotes: 8
Reputation: 41
Today i came across same kind of problem statement,i googled for solution for an hour and end up with no solution,the above all approaches are not correct solutions for the stated problem
The Better way to resolve above Problem is
Sort the two arrays either in ascending or descending order, Then compare both the arrays.
#include<stdio.h>
void sort_it(int a[], int size)
{
int i,j,temp=0;
for(i=0;i<size;++i)
{
for(j=i+1;j<size;++j)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
};
int compare(int size,int a[],int b[])
{
int i,j,is_equal;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)`enter code here`
{
if(a[i]!=b[j])
{
is_equal=0;
}
else
is_equal=1;
}
}
return is_equal;
};
int main()
{
int size=4,i,is_equal;
int a[]={1,2,5,4};
int b[]={1,7,4,2};
sort_it(a,size);
sort_it(b,size);
is_equal=compare(4,a,b);
if(is_equal)
printf("arrays are equal\n");
else
printf("arrays are not equal\n");
return (0);
}
Upvotes: -1
Reputation: 46365
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.
Upvotes: 17
Reputation: 3094
An implementation might be to loop over all the elements and set a flag when a difference is detected
int i, N;
int is_equal = 1;
for (i=1; i<N; ++i) {
if (a[i] != a_tmp[i]) {
is_equal = 0;
break;
}
}
if (is_equal)
printf("Arrays are equal");
Upvotes: 2