J'ai eu du mal à réaliser quelque chose de très simple en C afin de rendre plus dynamique l'un des programmes (non écrits par moi) de notre projet de physique informatique: : Comparer deux tableaux différents élément par élément dans un si conditionnel.
#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).
Le tableau a [] comporte un nombre variable d'éléments significatifs à chaque fois que nous exécutons notre programme; Par exemple, pour le moment, nous utilisons ce sous-programme uniquement pour les éléments [1] à [4]. Cependant, dans d'autres cas, nous souhaiterons avoir moins d'éléments ou plus, par exemple jusqu'à 3 éléments ou jusqu'à 5 éléments, respectivement.
Donc, essentiellement, je veux pouvoir réécrire l'énoncé if ci-dessus pour qu'il soit dynamique ... en d'autres termes, s'il y a N éléments pris en compte, alors cela fera :
if (a_tmp[1]==a[1] && ... && a_tmp[N]==a[N]){}
Donc, cela si conditionnel doit varier chaque fois que notre nombre N d’éléments d’intérêt est modifié (N est défini comme un #define dans l’en-tête de ce fichier, que je viens de nommer header.h).
J'apprécierais beaucoup votre soutien pour cette tâche. Je vous remercie.
Votre meilleur pari est de le réécrire sous forme de fonction renvoyant vrai ou faux (1 ou 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;
}
Notez que c’est généralement une mauvaise pratique de comparer les doubles pour l’égalité - vous feriez mieux de comparer leurs différences et de vous assurer que la valeur absolue est inférieure à une certaine tolérance.
Notez également que vous comparez les éléments 1 à n - les tableaux commencent par 0 si.
Vous utiliseriez ce qui précède avec
if (compareArrays(a, a_tmp, N)) {
où la valeur N
est #define
'd par votre question.
Si vous voulez être "malin" et éviter une boucle, vous pouvez écrire ce qui suit - ça va s'arrêter ("court-circuiter") dès que vous atteignez le bon nombre de comparaisons. C'est toujours une mauvaise idée de comparer les doubles pour l'égalité mais je vais laisser cela pour une autre fois (voir le commentaire dans le code ci-dessus pour une solution).
if(a[1]==a_temp[1] && (2 > N || (a[2]==a_temp[2] && (3 > N || (a[3]==a_temp[3]))))) {
Cela rend le "et le reste" true
dès que vous avez comparé le nombre correct de termes - ainsi, il cessera d’évaluer les termes (selon vos besoins). Je ne suis pas convaincu que ce soit un code plus rapide ou meilleur - mais c'est c'est "dynamique" ... Vous pouvez évidemment faire cette expression aussi longtemps que vous le souhaitez; Je viens d'écrire les trois premiers termes pour que vous compreniez bien l'idée. JE NE LE RECOMMANDE PAS.
En ce qui concerne la comparaison des doubles, vous pourriez envisager de remplacer
if(a == b)
avec
if(closeEnough(a, b))
où vous définissez la macro
#define closeEnough(a, b) (fabs((a)-(b)) < 1e-10 * (fabs(a) + fabs(b)))? 1 : 0
Cela fera en sorte que vos doubles ne doivent pas être "exactement égaux" - en fonction de la façon dont vous les avez obtenus, ils ne le seront presque jamais, et la tolérance relative d'une partie sur 10 ^ 10 est généralement suffisante pour la plupart des comparaisons pratiques .
Si cela doit être au moment de la compilation, rien dans la norme ne prévoit une macro répétitive comme celle-là. Comme dans un autre (question) , pour N borné, vous pouvez préparer N macros qui s’étendent à la comparaison souhaitée.
Même si une autre alternative est memcmp
memcmp( data, data2, array_len_in_bytes );
Une implémentation peut consister à parcourir tous les éléments et à définir un indicateur lorsqu'une différence est détectée.
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");
Une implémentation simple est une comparaison linéaire entre les deux tableaux, il suffit de parcourir la longueur du tableau et de vérifier if (a[i] != b[i])
; si tel est le cas, renvoyez false
& freinez l'itération.
Voir l'exemple ci-dessous:
#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;
break;
}
}
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;
}
Tu devrais obtenir:
Should be True 0
Should be False -1
Exécutez-le en ligne avec cet exemple: https://repl.it/@abranhe/compare-arrays-in-c