Сравнение структур
- Войдите на сайт для отправки комментариев
Пнд, 18/07/2022 - 19:44
Я хочу сравнить 4 структуры
struct{
float vin = 10.1;
float u0;
unsigned int switch_time;
unsigned int testing_time;
unsigned int number;
}m1;
struct{
float vin = 10.1;
float u0;
unsigned int switch_time;
unsigned int testing_time;
unsigned int number;
}m2;
struct{
float vin = 10.1;
float u0;
unsigned int switch_time;
unsigned int testing_time;
unsigned int number;
}m3;
struct{
float vin = 10.1;
float u0;
unsigned int switch_time;
unsigned int testing_time;
unsigned int number;
}m4;
Но у меня не получается так:
if (m1==m2&& m2==m3&&m3==m4){
}
выдает ошибку, мне нужно сравнивать каждые элементы структуры?
типо:
if (m1.vin == m2.vin && m2.vin == m3.vin && .....
Да, либо написать перегрузку оператора сравнения, и он «сделает это за вас».
ЗЫ:
struct{ float vin = 10.1; float u0; unsigned int switch_time; unsigned int testing_time; unsigned int number; } m1, m2, m3, m4;Сначала тебе нужно понять что такое структуры и зачем они нужны, чтобы не объявлять анонимно одинаковую структуру 4 раза.
Потом нужно написать оператор равенства, который будет проверять равенство всех элементов структуры. И не забыть, что равенство чисел с плавающей точкой определяется через эпсилон.
А как буду сравнивать?
например если m1 m2 m3 равны а m4 нет
struct{ float vin = 10.1; float u0; unsigned int switch_time; unsigned int testing_time; unsigned int number; } m1, m2, m3, m4;Сначала тебе нужно понять что такое структуры и зачем они нужны, чтобы не объявлять анонимно одинаковую структуру 4 раза.
Потом нужно написать оператор равенства, который будет проверять равенство всех элементов структуры. И не забыть, что равенство чисел с плавающей точкой определяется через эпсилон.
Я объявляю структуру 4 раза потому что мне надо сравнить 4 одинаковые структуры в памяти eeprom , хочу реализовать защиту от испорченности ячеек eeprom. Записываю структуру в 4 разные места а потом когда читаю хочу сравнить если они равны, или 3 из них раны тогда берем правильные данные
Ты реально непроходимо туп?
Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/
Ты реально непроходимо туп?
а как иначе реализовать это?
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#ga...
Я объявляю структуру 4 раза потому что мне надо сравнить 4 одинаковые структуры в памяти eeprom
совершенно никакой связи тут нет
а как иначе реализовать это?
зачем для этого описывать ТИП структуры 4 раза, когда тебе надо просто создать 4 ЭКЗЕМПЛЯРА , Ты понимаешь разницу между типом данных и экземпляром?
Структ это описание нового (комплексного) типа данных
далее этот новый тип данных можно использовать как обычно
обьявлять переменные сэтим типом
фирштеен зи?
фирштеен зи?
дождь...ди зонне шаинт нихт зо хель )))
Никакого "обычного ==" для структур нет.
Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/
Плохая идея.
В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.
Никакого "обычного ==" для структур нет.
Да, это я "с прямым углом перепутал", уже удалил глупость, сорри.
Петрович, Компилятор у меня такое не ест.
Нельзя структуры так сравнивать, только поэлементно.
Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/
Плохая идея.
В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.
На восьмибитной архитектуре вроде без дырок? Я по старой памяти ардуину на них натягиваю.
Но, если плохая, то плохая.
Float тоже напрямую не сравнишь, все равно где-то на побайтовое придётся прыгнуть.
Никакого "обычного ==" для структур нет.
Я, видимо, что-то упустил, но перегрузку операторов даже Си для мк должен поддерживать. Иначе какой это Си?...
Плохая идея.
В структуре могут быть "дырки" из-за выравнивания элементов.
#pragma pack(push,1) спасёт этого дурня.
Плохая идея.
В структуре могут быть "дырки" из-за выравнивания элементов.
#pragma pack(push,1) спасёт этого дурня.
Это на ESP у меня плохо кончалось - MK в кору падал.
на 32 или 8266?
8266 у мня есть, не заметил никаких косяков с этой прагмой, а ESP32 у мня нет, я их еще не заказывал на пащюпать, проверить не могу. :(((
В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.
А если "шлифануть" нулями (напрямую побайтно) после создания экземпляров есть шанс, что туда мусор попадет ? Так то вариант сравнения неплохой вроде.
на 32 или 8266?
8266 у мня есть, не заметил никаких косяков с этой прагмой, а ESP32 у мня нет, я их еще не заказывал на пащюпать, проверить не могу. :(((
https://arduino.ru/forum/programmirovanie/kod-krashit-esp8266
Я тут немного поговнокодил, посмотрите. Разместил две структуры в стеке. Одну до того, как слегка загадил стек, а другую - после. Так вот моё "загаживание" как раз попало в дырку и не дало структурам сравниться.
Затем, я воспользовался тупым присваиванием для структур - и вот тут-то они сравнились :-)
Так что, в этом говнокоде прекрасно всё :-)
#define printVar(x) do { Serial.print(#x); Serial.print('='); Serial.println(x); } while (false) // // Структура с дыркой // struct TheCat { byte m_b1; unsigned m_bit1 : 1; unsigned m_bit2 : 1; byte m_b2; byte m_b3; }; // // Нагадим немного в стек // void doACrap(void) { byte someArray[4]; memset(someArray, 0xFF, sizeof(someArray)); // Следующая строка - привет оптимизатору // если не взять адрес, то не разместит на стеке и не загадит printVar((unsigned) someArray); } // // Сравним структуры, расположенные в стеке // до его загаживания и после // void checkTheCat(TheCat & o) { TheCat c; // располагается в стеке ПОСЛЕ загаживания // // Обнуляем ВСЕ поля обеих структур c.m_b1 = c.m_b2 = c.m_b3 = c.m_bit1 = c.m_bit2 = o.m_b1 = o.m_b2 = o.m_b3 = o.m_bit1 = o.m_bit2 = 0; // // А они всё равно не равны! printVar(memcmp(&c, &o, sizeof(TheCat))); // c = o; // теперь тупо присвоим одну структуру другой // // А вот теперь равны! Похоже, присваивание через memcpy сделано printVar(memcmp(&c, &o, sizeof(TheCat))); }; void setup(void) { Serial.begin(57600); TheCat cat; // располагается в стеке ДО загаживания doACrap(); // теперь нагадим в стек checkTheCat(cat); } void loop(void) {}Согласитесь, гораздо проще так не писать, чем потом искать такие ошибки :-)
Не спорю. Но как правильно сравнить float?
Относительно первопостовой задачи, пожалуй, стоит хранить несколько экземпляров с CRC ? Где оно не совпало, там и проблема.
abs(a - b) < 0.0001
abs(a - b) < 0.0001
float a = 1.0e-12;
float b = 9.9e-12;
И?
Я так понял, равны?
В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.
В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.
Вопрос был, как сравнивать float. И вдруг, откуда ни возьмись, появляется какая-то задача.
Не нужно плодить сущности.
В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.
Вопрос был, как сравнивать float. И вдруг, откуда ни возьмись, появляется какая-то задача.
Не нужно плодить сущности.
или округляй обе величины и после этого уже сравнивай.
Этот прикол часто в экселе вылезает и пугает 1с-бухгалтерш.
или округляй обе величины и после этого уже сравнивай.
0.500000000000000000001
0.499999999999999999999
Андриано! В данном случае я тебя не понимаю. Ркит фактически написал, что побитовое или абсолютное сравнение для float не имеет математического смысла (вне контекста задачи). Да, так и есть. Я не могу понять твою позицию. Мог бы ты её озвучить?
Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.
А если уж и изобретать что-либо универсально, оно никогда не окажется простым.
Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.
или округляй обе величины и после этого уже сравнивай.
0.500000000000000000001
0.499999999999999999999
2. Ты не слишком ли много нулей с девятками наставил? float в ардуинстве пишется в 4 байта, это примерно 7 знаков на всё про всё.
Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.
На практике можно написать себе какую-нибудь функцию boolean equalFloat() по своему вкусу и втыкать её в большинство своих проектов. А в меньшинство с какими-нибудь астрономическими вычислениями не втыкать, сочинять что-то другое.
Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.
А если уж и изобретать что-либо универсально, оно никогда не окажется простым.
Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.
del
Допускать разницу в младших битах мантиссы - вот и относительность.
С младшими битами мантиссы - хорошая идея, я о ней думал, но проблема в том, что даже у достаточно близких (согласно выбранным критериям относительной точности) чисел могут различаться не только младшие, но даже старшие биты мантиссы. Пример был несколькими сообщениями назад.
или округляй обе величины и после этого уже сравнивай.
0.500000000000000000001
0.499999999999999999999
1 == 0 ?
или округляй обе величины и после этого уже сравнивай.
0.500000000000000000001
0.499999999999999999999
1 == 0 ?
Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.
А если уж и изобретать что-либо универсально, оно никогда не окажется простым.
Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.
Допускать разницу в младших битах мантиссы - вот и относительность.
С младшими битами мантиссы - хорошая идея, я о ней думал, но проблема в том, что даже у достаточно близких (согласно выбранным критериям относительной точности) чисел могут различаться не только младшие, но даже старшие биты мантиссы. Пример был несколькими сообщениями назад.
Пипец, мужики. Вроде ж, понедельник уже на дворе.
Вопрос же не про сравнение абстрактных float, где можно плюс-минус валенок допустить, а о сравнении считанных с трех мест хранения, при котором эти float должны быть эквивалентны. В противном случае определить сбой чтения/записи одного из трёх экземпляров наврядли возможно.
В таком случае float ничем не отличается от любого другого типа данных - только побитное совпадение.