如何对包含NaN的C的数组进行排序

问题描述 投票:-2回答:2

一直在尝试实现我的代码,作为对包括NaN在内的所有整数进行排序的方法。但似乎无法找到将NaN排序到我的程序中的函数。代码能够对包括无穷大在内的其他整数进行排序,但是当输入nan时,程序会识别输入,但不会将其排序到列表的开头。任何帮助,将不胜感激。

#include <stdio.h>
#include <math.h>

int main()
{
    float array[100], swap;
    int c, d, n;

    printf("Enter the size of array\n");
    scanf("%d", &n);

    printf("Enter %d integers\n", n);

    for (c = 0; c < n; c++)
        scanf("%f", &array[c]);

    for (c = 0; c < (n - 1); c++)
    {
        for (d = 0; d < n - c - 1; d++)
        {
            if (array[d] > array[d + 1]) 
            {
                swap = array[d];
                array[d] = array[d + 1];
                array[d + 1] = swap;
            }
        }
    }

    printf("Sorted array in ascending order:\n");


    for (c = 0; c < n; c++)
        printf("%f\n", array[c]);

    return 0;
}
c nan bubble-sort
2个回答
-1
投票

正如评论中所提到的,您的代码是C代码而不是C ++。这是你的C ++代码,附加条件应该可以解决你的问题:

#include <iostream>
#include <vector>
#include <cmath>

int main()
{
    std::size_t array_size;
    std::cout << "Enter the size of array\n";
    std::cin >> array_size;

    std::cout << "Enter " << array_size << " integers\n";

    std::vector<float> array(array_size);
    for(std::size_t i = 0; i < array.size(); ++i)
        std::cin >> array[i];

    for(std::size_t a = 0; a < array.size() - 1; ++a)
        for(std::size_t b = 0; b < array.size() - 1 - a; ++b)
            if(std::isnan(array[b + 1]) || array[b] > array[b + 1])
                std::swap(array[b], array[b + 1]);

    std::cout << "Sorted array in ascending order:\n";

    for(const auto& a : array)
        std::cout <<  a << '\n';

    return 0;
}

如果您不想自己编写所有排序的东西,可以使用更多的C ++和算法库(以及添加的输入检查)来完成:

template<typename T>
T get_input()
{
    T input;
    while(true)
    {
        std::cin >> input;
        if(std::cin)
            return input;
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "Invalid input! Please try again.\n";
    }
}

int main()
{
    std::cout << "Enter the size of array\n";
    std::size_t array_size = get_input<std::size_t>();

    std::cout << "Enter " << array_size << " integers\n";

    std::vector<float> input(array_size);
    for(auto& a : input)
        a = get_input<float>();

    std::sort(input.begin(), input.end(), [](const auto& a, const auto& b){ return std::isnan(a) || a < b; });

    std::cout << "Sorted array in ascending order:\n";

    for(const auto& a : input)
        std::cout << a << '\n';
}

1
投票

请注意,根据C标准,两个NaN值永远不会相等,即使它们具有相同的位模式。如果要使用NaN对数据进行排序,则需要:

  1. 决定NaN值应该在哪里排序w.r.t正确的值(通常选择是“在负无穷大之前”或“在正无穷大之后”)。
  2. 使用比简单的a > b比较更精细的测试。

您可以找到分散在C11标准周围的相关信息。例如:

你可能会安排创建一个函数(可能是一个inline函数,除非你要将它传递给像qsort()这样的函数),它比较相关类型的两个浮点值(看起来你使用的是float)使用isnan()isnanf()分类宏来确定其中一个或两个值是否为NaN。如果两个值都是NaN,函数可能会返回一个表示相等的值,但如果一个是NaN,则返回值将比其他值更早或更晚,具体取决于您希望NaN出现的顺序,它将返回用于比较其他值(正常值,零,无穷大,次正规数)的适当值 - 常规值和无穷大只需要常规比较运算符,除非您需要正确地将负零排序为正零。

例如,编写一个与qsort()一起使用的函数(并使用类型double而不是float)产生类似这样的东西,假设数字应该按升序排序,并且NaNs应该比任何其他值小。该代码包括用于从标准输入读取数据,打印,排序和再次打印的测试代码。

#include <math.h>

/* Belongs in a header! */
extern int cmp_double(const void *v1, const void *v2);

/* Sort doubles, with NaNs coming first */
/* Switch return values -1 and +1 after testing n1, n2 to sort NaNs last */
int cmp_double(const void *v1, const void *v2)
{
    double d1 = *(const double *)v1;
    double d2 = *(const double *)v2;
    int n1 = isnan(d1);
    int n2 = isnan(d2);

    if (n1 && n2)
        return 0;
    if (n1)
        return -1;
    if (n2)
        return +1;
    if (d1 < d2)
        return -1;
    if (d1 > d2)
        return +1;
    // The values are 'equal', but …
    if (d1 != 0.0)
        return 0;
    // They're both zero, but they could have different signs
    int s1 = signbit(d1);
    int s2 = signbit(d2);
    if (s1 != s2)
        return (s1) ? -1 : +1;
    return 0;
}

#include <stdio.h>
#include <stdlib.h>

static void dump_doubles(const char *tag, int num, double values[num])
{
    printf("%s (%d):\n", tag, num);
    int line_len = 0;
    for (int i = 0; i < num; i++)
    {
        int n = printf(" %+12.4f", values[i]);
        if (n <= 0)
            break;
        line_len += n;
        if (line_len >= 60)
        {
            line_len = 0;
            putchar('\n');
        }
    }
    if (line_len > 0)
        putchar('\n');
}

int main(void)
{
    enum { NUM_VALUES = 50 };
    double values[NUM_VALUES];

    int i = 0;

    for (i = 0; i < NUM_VALUES; i++)
    {
        if (scanf("%lf", &values[i]) != 1)
            break;
    }

    dump_doubles("Before sort", i, values);
    qsort(values, i, sizeof(values[0]), cmp_double);
    dump_doubles("After sort", i, values);

    return 0;
}

注意在+0.0之前排序-0.0所需的测试!

考虑输入数据:

3023.421800 9033.902200 nan -9370.952500 3088.884900 6829.135400 0
-0.000000 -inf -5267.546800 -8784.373300 5663.944600 -9728.231300 inf
-inf -5373.038600 4282.941600 6245.734200 -5533.975400 nan 8445.713600
+inf -9108.960400 -3796.671200 nan -2363.851300 877.460400 9936.416900
-3480.867400

那个输出是:

Before sort (29):
   +3023.4218   +9033.9022          nan   -9370.9525   +3088.8849
   +6829.1354      +0.0000      -0.0000         -inf   -5267.5468
   -8784.3733   +5663.9446   -9728.2313         +inf         -inf
   -5373.0386   +4282.9416   +6245.7342   -5533.9754          nan
   +8445.7136         +inf   -9108.9604   -3796.6712          nan
   -2363.8513    +877.4604   +9936.4169   -3480.8674
After sort (29):
          nan          nan          nan         -inf         -inf
   -9728.2313   -9370.9525   -9108.9604   -8784.3733   -5533.9754
   -5373.0386   -5267.5468   -3796.6712   -3480.8674   -2363.8513
      -0.0000      +0.0000    +877.4604   +3023.4218   +3088.8849
   +4282.9416   +5663.9446   +6245.7342   +6829.1354   +8445.7136
   +9033.9022   +9936.4169         +inf         +inf
© www.soinside.com 2019 - 2024. All rights reserved.