Is the defacto method for comparing arrays (in C) to use memcmp
from string.h
?
I want to compare arrays of ints and doubles in my unit tests
I am unsure whether to use something like:
double a[] = {1.0, 2.0, 3.0};
double b[] = {1.0, 2.0, 3.0};
size_t n = 3;
if (! memcmp(a, b, n * sizeof(double)))
/* arrays equal */
or to write a bespoke is_array_equal(a, b, n)
type function?
compareArray() will compare elements of both of the array elements and returns 0 if all elements are equal otherwise function will return 1.
While comparing two arrays we can not use “==” operator as it will compare the addresses of the memory block to which both the arrays are pointing.
Using Arrays. equals(array1, array2) methods − This method iterates over each value of an array and compare using equals method. Using Arrays. deepEquals(array1, array2) methods − This method iterates over each value of an array and deep compare using any overridden equals method.
memcmp
would do an exact comparison, which is seldom a good idea for floats, and would not follow the rule that NaN != NaN. For sorting, that's fine, but for other purposes, you might to do an approximate comparison such as:
bool dbl_array_eq(double const *x, double const *y, size_t n, double eps)
{
for (size_t i=0; i<n; i++)
if (fabs(x[i] - y[i]) > eps)
return false;
return true;
}
Using memcmp
is not generally a good idea. Let's start with the more complex and work down from there.
Though you mentioned int
and double
, I first want to concentrate on memcmp
as a general solution, such as to compare arrays of type:
struct {
char c;
// 1
int i;
// 2
}
The main problem there is that implementations are free to add padding to structures at locations 1 and 2, making a bytewise comparison potentially false even though the important bits match perfectly.
Now down to doubles. You might think this was better as there's no padding there. However there are other problems.
The first is the treatment of NaN
values. IEEE754 goes out of its way to ensure that NaN
is not equal to any other value, including itself. For example, the code:
#include <stdio.h>
#include <string.h>
int main (void) {
double d1 = 0.0 / 0.0, d2 = d1;
if (d1 == d2)
puts ("Okay");
else
puts ("Bad");
if (memcmp (&d1, &d2, sizeof(double)) == 0)
puts ("Okay");
else puts
("Bad");
return 0;
}
will output
Bad
Okay
illustrating the difference.
The second is the treatment of plus and minus zero. These should be considered equal for the purposes of comparison but, as the bit patterns are different, memcmp
will say they are different.
Changing the declaration/initialisation of d1
and d2
in the above code to:
double d1 = 0.0, d2 = -d1;
will make this clear.
So, if structures and doubles are problematic, surely integers are okay. After all, they're always two's complement, yes?
No, actually they're not. ISO mandates one of three encoding schemes for signed integers and the other two (ones' complements and sign/magnitude) suffer from a similar problem as doubles, that fact that both plus and minus zero exist.
So, while they should possibly be considered equal, again the bit patterns are different.
Even for unsigned integers, you have a problem (it's also a problem for signed values as well). ISO states that these representations can have value bits and padding bits, and that the values of the padding bits are unspecified.
So, even for what may seem the simplest case, memcmp
can be a bad idea.
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