Стандартное отклонение и дисперсия массива чисел

Ищете простой способ получить дисперсию массива чисел, который будет скомпилирован с помощью компилятора Arduino. Что-то вроде этого c #:

static float variance(double []a, int n)
{
    // Вычислить среднее значение (среднее значение элементов)
    double sum = 0;

    for (int i = 0; i < n; i++) sum += a[i];
    double mean = (double)sum / (double)n;
    // Вычислить сумму квадратов разностей со средним значением.
    double sqDiff = 0;
    for (int i = 0; i < n; i++)
        sqDiff += (a[i] - mean) * (a[i] - mean);
    return (float)sqDiff / n;
}


// Код драйвера
public static void Main ()
{
    double []arr = {10, 11, 12, 13};
    int n = arr.Length;
    Console.WriteLine( "Variance: " + variance(arr, n));
}

Чтобы все было просто, и спасибо за всю вашу помощь.... это платформа с приводами в каждом углу для подъема и опускания платформы.... Каждый исполнительный механизм отправляет обратную связь по modbus на главный микропроцессор по своему запросу Который сохраняется в массиве, который обрабатывается и затем отправляется через modbus Возврат к управлению (простое включение/выключение) каждым приводом для удержания платформы в некотором ровном положении +/- установленное число.... Я уже использую min / max (max – min = ) в моем коде, чтобы ограничить набор простых различий между Исполнительные механизмы.... Я думаю, что использование дифференциала дисперсии будет лучше работать для приложения.... Полагая, что это также позволит обнаружить заклинивший или неисправный привод быстрее, чем разница max / min с Меньше скручивания платформы.... (Ответ Эдгару), Вы могли бы рассматривать это как XYZ, ... X = позиция.. Y= привод.. Z= частота дискретизации

Это мой код, отрежьте его для максимального / минимального

пример 1 — adj_str = положение исполнительных механизмов = (10,11,10,9) флаг уровня запуска 1

пример 2 — adj_str = положение исполнительных механизмов = (10,14,10,9) флаг уровня запуска 0

void min_max()
{
    int max = adj_str[0];
    int min = adj_str[0];
    for (int i = 0; i <= 3; i++)
    {
        const int value = adj_str[i];
        if (value > max) max = value ;
        if (value < min) min = value ;
    }
    //-
    adj_str_dif = max - min;
    //-
    if (adj_str_dif < 1) level_flag = 1;
    //-
    if ((level_flag == 1)&&(adj_str_dif > 4))  // 4 = дифференциал
    { level_flag = 0;}
    //-
    if (level_flag == 0)           // Уровень до максимального или минимального (повторный уровень)
    {
        // -- Нижний --
        if (adj_str_dif > 0 && (digitalRead(but_pin[1]) == LOW))
            base = (max);
        // -- Поднять --
        if (adj_str_dif > 0 && (digitalRead(but_pin[2]) == LOW))
            base = (min);
    }
    //-
    if (level_flag == 1)       // Выполнять до полного втягивания или полного выдвижения
    {
        // -- Нижний --
        if (adj_str_dif < 1 && (digitalRead(but_pin[1]) == LOW))
            base = 1023;
        // -- Поднять --
        if (adj_str_dif < 1 && (digitalRead(but_pin[2]) == LOW))
            base = 0;
    }
}

, 👍-1

Обсуждение

общий вопрос программирования ... не вопрос , связанный с arduino... здесь не по теме ... пожалуйста, напишите по адресу https://stackoverflow.com/questions вместо этого, @jsotola

Ваш пример кода принимает массив двойных значений; вы действительно хотите использовать входные данные из строки? Из одной строки, содержащей все данные? Может быть, через запятую? Возможно, с разрешенным, но игнорируемым пробелом (только между значениями, а не внутри любого), .... Таким образом, ваш вопрос не только не специфичен для Arduino, но и недостаточно конкретизирован, чтобы иметь возможность ответить на него. Предполагая, что я угадал правильно, вам нужно будет прочитать строку, собрать каждое значение, преобразовать его в double и поместить в массив, который будет передан как 'a' вашей функции 'variance()'., @JRobert

пример кода взят из https://www.geeksforgeeks.org/program-for-variance-and-standard-deviation-of-an-array/, @Eric V

JRoberts..... пример кода взят из [ссылка] https://www.geeksforgeeks.org/program-for-variance-and-standard-deviation-of-an-array /) ..... я надеялся немного изменить это, чтобы запустить некоторые тесты в Arduino IDE .... у меня уже есть настройка строки, которая содержит несколько показаний АЦП, и если я прав в мое предположение, что я могу использовать результат отклонения, чтобы отметить выполнение.. мне действительно нравится колоколообразная кривая, которую он создает, и я думаю, что это может сработать для моего проекта, @Eric V

Это очень похоже на проблему [XY] (https://xyproblem.info /). Кажется, вы задаете неправильный вопрос по нескольким причинам: 1. Если ваши данные поступают из АЦП Arduino, преобразование чисел в строку только для того, чтобы преобразовать их обратно в числа, бесполезно и невероятно расточительно. 2. Этот алгоритм для определения дисперсии требует, чтобы вы дважды прочитали массив. Не тот метод, который вы хотите использовать на микроконтроллере. Вы хотите сделать это за один проход, когда считываете данные АЦП, поэтому вам никогда не придется сохранять результаты измерений. Пожалуйста, расскажите нам, чего вы на самом деле хотите достичь., @Edgar Bonet

Эрик, где ты пишешь строку, ты имел в виду массив?, @Juraj

@Juraj: Как свидетельствует его пример кода (в основном типа adj_str), он действительно означает “массив чисел”. Я отредактировал вопрос, чтобы избежать путаницы., @Edgar Bonet

Пожалуйста, обратите внимание, что вычисление среднего значения путем сложения всех чисел и деления на количество является [не очень хорошим методом при использовании арифметики с плавающей запятой] (https://www.nu42.com/2015/03/how-you-average-numbers.html ). Затем использование этого среднего значения в расчетах дисперсии чревато большими ошибками. [онлайн algorithm](https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm ) работает намного лучше, а также удобен для запоминания. Числовая стабильность и корректность алгоритма начинают иметь большое значение для тех, кто использует вычисления для управления внешними устройствами., @Sinan Ünür

Я пропустил описание вашей проблемы относительно "не компилируется с компилятором Arduino" (помимо изменений c # на arduino c ++), @DataFiddler

(Int adj_str [4]; ) обновляется при каждом опросе ведомого устройства, чтобы уточнить ... я рассматривал это как весь набор данных для этого момента во время путешествия .... я еще раз проверю онлайн-алгоритм Уэлфорда, может работать лучше, чем стандартное отклонение дисперсии это было опубликовано и понравилось за один проход ! ..... я могу показаться немного дислексией, но мне нравится термин "амбидекстрий" .... у меня еще не было возможности протестировать обновленную версию Juraj, @Eric V


1 ответ


1

Базовые языковые конструкции C ++ и C # (или Java) очень похожи. Вот версия Arduino вашего кода на C # с минимальными необходимыми изменениями. Никаких изменений в реализации функции не произошло.


float variance(double a[], int n) 
{   
    // Compute mean (average of elements) 
    double sum = 0; 
    
    for (int i = 0; i < n; i++) sum += a[i];    
    double mean = (double)sum / (double)n; 
    // Compute sum squared differences with mean. 
    double sqDiff = 0; 
    for (int i = 0; i < n; i++) 
        sqDiff += (a[i] - mean) * (a[i] - mean); 
    return (float)sqDiff / n; 
} 


void setup() {
    Serial.begin(115200);
    double arr[] = {10, 11, 12, 13}; 
    int n = sizeof(arr) / sizeof(double); 
    Serial.print( "Variance: ");
    Serial.println(variance(arr, n));                            
}

void loop() {

}
,

Спасибо... попробую запустить это позже сегодня вечером, @Eric V

Работает так, как указано, @Eric V