【问题标题】:Comparing two arrays in C, element by element比较C中的两个数组,逐个元素
【发布时间】:2014-06-11 02:48:47
【问题描述】:

我一直在努力用 C 语言实现一些非常简单的东西,以使我的计算物理项目中的一个程序(不是我编写的)更具动态性: 在 if 条件下逐个元素地比较两个不同的数组。

#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).

每次我们运行程序时,数组a[ ] 都有不同数量的重要元素;例如,现在,我们只对元素 [1][4] 使用这个子例程。但是,在其他情况下,我们会希望元素更少或更多,例如最多 3 个元素或最多 5 个元素。

所以本质上,我希望能够重写上面的 if 语句,使其是动态的......换句话说,如果考虑了 N 个元素,那么它会这样做::: p>

if (a_tmp[1]==a[1] &amp;&amp; ... &amp;&amp; a_tmp[N]==a[N]){}

因此,只要我们感兴趣的元素的数量 N 发生变化,这个 if 条件就会发生变化(N 在此文件的标题中定义为 #define,我刚刚将其命名为 header.h)。

非常感谢您对这项任务的支持。谢谢。

【问题讨论】:

  • 比较doubles 是否相等通常是个坏主意。
  • 我推断您出于“性能原因”故意避开循环是吗?如果是这样,您应该真正运行分析器以确保您手动扩展的解决方案实际上更快。即使是这样,它也有助于量化您所追求的收益。
  • memcmp(&amp;a_tmp[1], &amp;a[1], 4 * sizeof a[1]);

标签: c arrays


【解决方案1】:

最好的办法是将其重写为返回真或假(1 或 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;
}

请注意,比较双精度值是否相等通常是不好的做法 - 最好比较它们的差异,并确保绝对值小于某个容差。

另请注意,您正在比较元素 1 到 n - C 数组虽然从 0 开始。

你可以用上面的

if (compareArrays(a, a_tmp, N)) {

根据您的问题,N 的值是 #define

如果您想“聪明”并避免循环,您可以编写以下内容 - 一旦您达到正确的比较次数,它将停止(“短路”)。 仍然比较双精度数是否相等是个坏主意,但我会再等一次(有关解决方案,请参阅上面代码中的注释)。

if(a[1]==a_temp[1] && (2 > N || (a[2]==a_temp[2] && (3 > N || (a[3]==a_temp[3]))))) {

只要您比较了正确数量的术语,这就会生成“和其余的”true - 因此它将停止评估术语(根据您的需要)。我不相信这是更快或更好的代码 - 但它“动态的”......您显然可以根据需要制作这个表达式;我刚刚写了前三个术语,所以你明白了。我不推荐它。

至于双打的比较,你可以考虑替换

if(a == b)

if(closeEnough(a, b))

定义宏的位置

#define closeEnough(a, b) (fabs((a)-(b)) < 1e-10 * (fabs(a) + fabs(b)))? 1 : 0

这将确保您的双打不必“完全相等” - 取决于您如何获得它们,它们几乎永远不会如此,并且 10^10 中 1 部分的相对公差通常足以最实际的比较。

【讨论】:

  • +1 对浮点数比较问题的扎实讨论
  • 感谢您的详尽回答! “compareArrays”是否应该将double a[]double b[] 作为参数?也感谢关于双打平等的讨论。
  • @LightningXI - 你是对的,参数应该是指针。我会更新的。
【解决方案2】:

如果它必须在编译时进行,那么标准中没有任何内容提供这样的重复宏。与另一个 (question) 一样,对于有界 N,您可以准备 N 个宏来扩展您想要的比较。

而另一种选择是 memcmp

memcmp( data, data2, array_len_in_bytes );

reference

【讨论】:

  • 为了完整性:请注意arraylen 是数组长度,单位为 bytes 而不是 elements,比较 doubles 是否相等并不是什么好办法主意;但有趣的建议是使用memcmp
  • 我从未考虑过memcmp。我很欣赏这个解决方案。
【解决方案3】:

一种实现可能是遍历所有元素并在检测到差异时设置一个标志

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

【讨论】:

  • 请注意,问题中的代码似乎比较了从[1] 开始的元素......很奇怪,但确实如此。
  • 好点,但我只是试图说明这个概念,而不是提供现成的定制代码。我看到我们提出了相同的概念:)
  • 是的。 [0] 元素实际上是为其他东西保留的,因此比较适用于从 [1] 开始。很抱歉没有澄清这一点。
【解决方案4】:

一个简单的实现是两个数组之间的线性比较,它只是遍历数组长度并检查if (a[i] != b[i]),如果是,则返回false并退出迭代。

请看下面的例子:

#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;
}

你应该得到:

Should be True 0
Should be False -1

在线运行这个例子:https://repl.it/@abranhe/compare-arrays-in-c

【讨论】:

    【解决方案5】:

    这个可以让你比较两个任意类型的数组,并返回找到的第一个不相等元素的索引。如果数组相同,则返回值将是数组中的元素数。

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

    一个示例调用:

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

    【讨论】:

      【解决方案6】:

      今天我遇到了同样的问题陈述,我搜索了一个小时的解决方案,最终没有解决方案,以上所有方法都不是针对所述问题的正确解决方案

      解决上述问题的更好方法是

      将两个数组按升序或降序排序,然后比较两个数组。

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

      【讨论】:

      • 问题陈述中没有任何内容表明需要比较元素,无论它们在数组中的顺序如何。这可能是您需要的 - 但我不相信这是 OP 要求的。
      猜你喜欢
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 2016-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多