LightningXI
LightningXI

Reputation: 103

Comparing two arrays in C, element by element

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

Answers (6)

Paul K
Paul K

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

Abraham
Abraham

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

dwerner
dwerner

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 );

reference

Upvotes: 8

Lax
Lax

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

Floris
Floris

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

Pankrates
Pankrates

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

Related Questions