【问题标题】:Eliminating NaN Values from an array in C从 C 中的数组中消除 NaN 值
【发布时间】:2021-01-18 12:54:17
【问题描述】:

我试图清理给定数组示例中的“NaN”变量; 我的输入数组 A 是:

float A[] = { 5.0f, NAN, 1.5f, 0.0f, 1.75f };

预期的输出数组 A 是:

{5.0f,1.5f, 0.0f, 1.75f}

我可以删除每个 NAN 并将元素向左移动一次。 但是如果数组太大而无法处理,就会成为低效的算法。

我在 C 中找不到任何解决方案。 所以我的问题是有没有比这些方法更有效的解决方案?

问候。

【问题讨论】:

  • (a) “将元素向左移动一次”是什么意思?显示代码,或者至少是伪代码,解释你的意思。 (b) C 中的数组是一组连续分配的特定类型的对象。如果输出数组要包含非 NaN 值,则它们必须移动到该位置。如果输出是一个数组,就没有办法了。可能有快速的方法可以做到这一点,并且可能有其他方法可以管理数据而不是作为数组。
  • 我的意思是,我可以检测到“NaN”值。然后获取该变量的索引(例如 a)。在数组的最后一个元素之前,它看起来像 array[a] = array[a+1]。
  • 每次找到 NaN 时,都不需要在 array[a] = array[a+1] 上进行迭代。你能想到另一种算法吗?
  • 好吧,例如,如果我使用的是现代 C++,我可以使用 STL 库和向量作为容器,所有的工作都只是使用擦除方法。所以我在 C 中寻找类似的解决方案。
  • 你必须以某种方式填补空白......

标签: arrays c algorithm


【解决方案1】:

从 C 中的数组中消除 NaN 值

这里关于 NaN 没有什么特别之处。要从数组中删除一个值,请遍历数组。

// `isnan()`
#include <math.h>

// In place solution
float A[] = { 5.0f, NAN, 1.5f, 0.0f, 1.75f };
size_t n = sizeof A/sizeof A[0];
size_t w = 0; 
for (size_t r = 0; r < n; r++) {
  if (!isnan(A[r]) {
    A[w++] = A[r];
  }
}
// Array size is still `n`, yet the first `w` elements are of interest.

要创建一个新数组,代码可以形成一个 VLA 并遍历 A[] 两次,第一次确定大小,第二次读取和复制。

// New array solution
float A[] = { 5.0f, NAN, 1.5f, 0.0f, 1.75f };
size_t n = sizeof A/sizeof A[0];

size_t new_n = 0;
for (size_t r = 0; r < n; r++) {
  if (!isnan(A[r]) new_n++;
}

if (new_n == 0) TBD_code();  // VLA must be at least 1
float new_A[new_n];
size_t w = 0; 
for (size_t r = 0; r < n; r++) {
  if (!isnan(A[r]) {
    new_A[w++] = A[r];
  }
}

【讨论】:

    【解决方案2】:

    有一个使用two pointers techniqueO(n) 解决方案。可以将所有 NaN 术语交换到数组的末尾,同时保留非 NaN 术语的相对顺序。
    p 记录遇到了多少非 NaN 术语并将其返回以保留跟踪A的当前大小。

    int moveNAN(float A[], int n)
    {
        int p = 0;
        for(int i = 0; i < n; ++i)
            if(!isnan(A[i]))  // if `isnan` is not defined use `A[i] == A[i]` (NaN values return false)
            {
                if(p != i)
                    swap(A[i], A[p]);
                ++p;
            }
        return p;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-22
      • 1970-01-01
      • 2014-06-07
      • 2020-04-21
      • 2018-12-21
      • 2016-12-10
      • 1970-01-01
      • 2019-04-15
      相关资源
      最近更新 更多