Распечатать числа с плавающей запятой массива и соответствующее количество каждого из них

Я пытался написать программу на C, которая по массиву с плавающей запятой определяет, сколько существует каждого числа, а затем печатает каждое число и соответствующую ему частоту. Это упражнение из моего колледжа (курс информатики). В общей сложности я, должно быть, потратил около 3 часов, пытаясь обдумать решение, и просто не могу думать. Хотя я уверен, что это мелочь.

Я не мог разработать ничего, что, по моему мнению, сработало бы. Если я пойду в VS и попытаюсь что-то запрограммировать, чтобы решить эту проблему, мой разум застынет в тот момент, когда мне нужно будет подумать, как представить механизм, который заставляет компьютер «знать», если число в данной позиции и его частота уже учтены. for before в массиве частот (int).

(Для всеобщего понимания, я изменил текст выше после публикации, потому что забыл слово «массив» и неправильно перевел на английский. На португальском (мой родной язык) это «ветор», поэтому я предположил, что это «вектор», это еще одно существующее английское слово. Однако оно, похоже, не используется так часто, как «массив», для обозначения этого в дискуссиях по английскому программированию.)

#include <stdio.h>

#define VEC_LEN 8

int main(void)
{
    int vFreq[VEC_LEN] = { 0, 0, 0, 0, 0, 0, 0 ,0 };
    float vNums[VEC_LEN] = { 1.5, -4.8, 2.9, 6.1, 4.2, 1.5, 2.9, 6.1 };

    for (int i = 0; i < VEC_LEN; i++)
    {
        float n = vNums[i];
        for (int j = 0; j < VEC_LEN; j++)
        {
            if (n == vNums[j])
                vFreq[i]++;

            // then my brain freezes
        }
    }
        


    return 0;
}

Кстати: зачем использовать объекты float с константами double? В C здесь более идиоматично использовать объекты double.

chux - Reinstate Monica 05.06.2024 03:03

Возможно, вы хотите добавить третий массив, например float vCountedNums[VEC_LEN];, и когда вы впервые увеличиваете vFreq[i] до 1, также установите vCountedNums[i] = n;. Таким образом, у вас будет возможность «запомнить», что счетчик, присутствующий в vFreq[i], соответствует значению с плавающей запятой, указанному в vCountedNums[i].

Jeremy Friesner 05.06.2024 03:05

Вы уверены, что все числа конечны (ни бесконечности, ни NaN) и что вам не придется иметь дело с 0.0 и -0.0?

Nate Eldredge 05.06.2024 09:04

@NateEldredge да

rafamussap 05.06.2024 13:09

Разрешено ли вам изменять массив?

Gerhardh 05.06.2024 13:17

@Gerhardh Да, я думаю, никаких ограничений на этот счет нет. Просто нужно напечатать каждое число и его частоты в каждой строке вывода.

rafamussap 05.06.2024 13:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
96
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я не буду давать полное решение на языке C. Поскольку вы проходите «курс информатики», я думаю, вам лучше решить эту задачу самостоятельно. Но вот описание алгоритма, который вы можете реализовать.

Начните с сортировки массива vNums. Для этого вы будете использовать qsort.

После сортировки ваш массив будет выглядеть так:

{ -4.8, 1.5, 1.5, 2.9, 2.9, 4.2, 6.1, 6.1 }

Затем вы перебираете отсортированный массив и подсчитываете последовательные равные элементы. Когда два последовательных элемента равны, увеличьте счетчик и перейдите к следующему элементу. Если два последовательных элемента различаются, вы печатаете первый вместе со значением счетчика, а затем перезапускаете подсчет. В псевдокоде что-то вроде:

count = 1
current_value = sorted_array[0]
index = 1
while index < number_of_element_in_sorted_array
{
    if (current_value == sorted_array[index])
    {
        count = count + 1
    }
    else
    {
        print current_value and count
        count = 1
        current_value = sorted_array[index]
    }
    index = index + 1
}
print current_value and count

@rafamussap причина сортировки - ускорить работу программы. Учтите следующее: при сортировке одинаковые числа также являются соседними в массиве, поэтому вы можете сканировать отсортированный массив только один раз. Вы начинаете отсчет со следующего числа, пока оно не станет отличаться от предыдущего числа, затем записываете счет и возобновляете счет с этого числа. Если массив не отсортирован, придется заново сканировать весь массив и отслеживать, какие числа вы уже учли. Попробуйте с {1.4, -9.1, 2.0, 1.4, 5.6, 1.4, -9.1}. К тому времени, как вы увидите второй 1.4, вы должны знать, что вы уже это учли.

Remo.D 05.06.2024 16:33

@rafamussap. Если можно, общее предложение. Когда вы попытаетесь решить подобные упражнения, забудьте о компьютере. Возьмите ручку и бумагу и нарисуйте набросок, изображающий ситуацию (в данном случае список чисел). Когда вы станете более опытным, вы сможете делать это в уме, но пытаться решить эти проблемы без четкого представления о том, что происходит, очень и очень сложно (и может разочаровывать). Только после того, как вы уверены в том, ЧТО вам нужно сделать, вы можете сосредоточиться на том, чтобы рассказать компьютеру, КАК это сделать.

Remo.D 05.06.2024 16:43

Как упоминал Джереми, вам нужен третий массив [возможно].

  1. vNums исходный массив с числами
  2. vMatch содержит значение из vNums для данного сегмента частоты.
  3. vFreq содержит количество для данного сегмента частоты

Или, используя struct, последние два массива можно объединить в один [предпочтительно]


Вот исправленный код для версии с тремя массивами:

#include <stdio.h>

#define VEC_LEN 8

int
main(void)
{
    int vFreq[VEC_LEN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    double vMatch[VEC_LEN] = { 0 };
    double vNums[VEC_LEN] = { 1.5, -4.8, 2.9, 6.1, 4.2, 1.5, 2.9, 6.1 };
    int freqcount = 0;
    int freqidx;

    // loop through all values
    for (int i = 0; i < VEC_LEN; i++) {
        // get current value
        double n = vNums[i];

        // look for match to already existing entry in frequency table
        for (freqidx = 0;  freqidx < freqcount;  ++freqidx) {
            if (n == vMatch[freqidx])
                break;
        }

        // no existing match found -- add new entry
        if (freqidx >= freqcount) {
            vMatch[freqidx] = n;
            freqcount += 1;
        }

        // increase the frequency count
        vFreq[freqidx] += 1;
    }

    // print all frequencies
    for (freqidx = 0;  freqidx < freqcount;  ++freqidx)
        printf("Value: %.1f Frequency: %d\n",vMatch[freqidx],vFreq[freqidx]);

    return 0;
}

Вот результат:

Value: 1.5 Frequency: 2
Value: -4.8 Frequency: 1
Value: 2.9 Frequency: 2
Value: 6.1 Frequency: 2
Value: 4.2 Frequency: 1

Вот версия, которая имеет два массива и использует struct и указатель:

#include <stdio.h>

#define VEC_LEN 8

struct freq {
    double freq_match;
    int freq_count;
};

int
main(void)
{
    struct freq freq_table[VEC_LEN] = { 0 };
    double vNums[VEC_LEN] = { 1.5, -4.8, 2.9, 6.1, 4.2, 1.5, 2.9, 6.1 };
    int freqcount = 0;
    int freqidx;
    struct freq *freq;

    // loop through all values
    for (int i = 0; i < VEC_LEN; i++) {
        // get current value
        double n = vNums[i];

        // look for match to already existing entry in frequency table
        freq = freq_table;
        for (freqidx = 0;  freqidx < freqcount;  ++freqidx, ++freq) {
            if (n == freq->freq_match)
                break;
        }

        // no existing match found -- add new entry
        if (freqidx >= freqcount) {
            freq->freq_match = n;
            freqcount += 1;
        }

        // increase the frequency count
        freq->freq_count += 1;
    }

    // print all frequencies
    freq = freq_table;
    for (freqidx = 0;  freqidx < freqcount;  ++freqidx, ++freq)
        printf("Value: %.1f Frequency: %d\n",freq->freq_match,freq->freq_count);

    return 0;
}

Вот вывод программы:

Value: 1.5 Frequency: 2
Value: -4.8 Frequency: 1
Value: 2.9 Frequency: 2
Value: 6.1 Frequency: 2
Value: 4.2 Frequency: 1

Вот расширенная версия, которая исключает freqidx и использует макрос для циклов for:

#include <stdio.h>

#define VEC_LEN 8

struct freq {
    double freq_match;
    int freq_count;
};

#define FREQ_FORALL \
    freq = &freq_table[0];  freq < &freq_table[freqcount];  ++freq

int
main(void)
{
    struct freq freq_table[VEC_LEN] = { 0 };
    double vNums[VEC_LEN] = { 1.5, -4.8, 2.9, 6.1, 4.2, 1.5, 2.9, 6.1 };
    int freqcount = 0;
    struct freq *freq;

    // loop through all values
    for (int i = 0; i < VEC_LEN; i++) {
        // get current value
        double n = vNums[i];

        // look for match to already existing entry in frequency table
        for (FREQ_FORALL) {
            if (n == freq->freq_match)
                break;
        }

        // no existing match found -- add new entry
        if (freq >= &freq_table[freqcount]) {
            freq->freq_match = n;
            freqcount += 1;
        }

        // increase the frequency count
        freq->freq_count += 1;
    }

    // print all frequencies
    for (FREQ_FORALL)
        printf("Value: %.1f Frequency: %d\n",freq->freq_match,freq->freq_count);

    return 0;
}

Другие вопросы по теме