Сравнение структур

Maliyev
Offline
Зарегистрирован: 11.07.2022

Я хочу сравнить 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 && .....

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да, либо написать перегрузку оператора сравнения, и он «сделает это за вас».

ЗЫ:

struct{
  float vin = 10.1;
  float u0;
  unsigned int switch_time;
  unsigned int testing_time;
  unsigned int number;
} m1, m2, m3, m4;

 

rkit
Offline
Зарегистрирован: 23.11.2016

Сначала тебе нужно понять что такое структуры и зачем они нужны, чтобы не объявлять анонимно одинаковую структуру 4 раза.

Потом нужно написать оператор равенства, который будет проверять равенство всех элементов структуры. И не забыть, что равенство чисел с плавающей точкой определяется через эпсилон.

Maliyev
Offline
Зарегистрирован: 11.07.2022

А как буду сравнивать?

например если 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;

 

Maliyev
Offline
Зарегистрирован: 11.07.2022

rkit пишет:

Сначала тебе нужно понять что такое структуры и зачем они нужны, чтобы не объявлять анонимно одинаковую структуру 4 раза.

Потом нужно написать оператор равенства, который будет проверять равенство всех элементов структуры. И не забыть, что равенство чисел с плавающей точкой определяется через эпсилон.

Я объявляю структуру 4 раза потому что мне надо сравнить 4 одинаковые структуры в памяти eeprom , хочу реализовать защиту от испорченности ячеек eeprom. Записываю структуру в 4 разные места а потом когда читаю хочу сравнить если они равны, или 3 из них раны тогда берем правильные данные

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ты реально непроходимо туп?

sadman41
Offline
Зарегистрирован: 19.10.2016

Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/

Maliyev
Offline
Зарегистрирован: 11.07.2022

DetSimen пишет:

Ты реально непроходимо туп?

а как иначе реализовать это?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017
rkit
Offline
Зарегистрирован: 23.11.2016

Maliyev пишет:

Я объявляю структуру 4 раза потому что мне надо сравнить 4 одинаковые структуры в памяти eeprom

совершенно никакой связи тут нет

b707
Offline
Зарегистрирован: 26.05.2017

Maliyev пишет:

а как иначе реализовать это?

зачем для этого описывать ТИП структуры 4 раза, когда тебе надо просто создать 4 ЭКЗЕМПЛЯРА , Ты понимаешь разницу между типом данных и экземпляром?

inspiritus
Offline
Зарегистрирован: 17.12.2012

Структ это описание нового (комплексного) типа данных

далее этот новый тип данных можно использовать как обычно

обьявлять переменные сэтим типом

фирштеен зи?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

inspiritus пишет:

фирштеен зи?

дождь...ди зонне шаинт нихт зо хель )))

rkit
Offline
Зарегистрирован: 23.11.2016

Никакого "обычного ==" для структур нет.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/

Плохая идея.

В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

rkit пишет:

Никакого "обычного ==" для структур нет.

Да, это я "с прямым углом перепутал", уже удалил глупость, сорри.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Петрович, Компилятор у меня такое не ест.

Нельзя структуры так сравнивать, только поэлементно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kakmyc пишет:
Петрович, Компилятор у меня такое не ест.
См. #15

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

sadman41 пишет:

Если просто чекнуть на совпадение нужно, то https://cplusplus.com/reference/cstring/memcmp/

Плохая идея.

В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.


На восьмибитной архитектуре вроде без дырок? Я по старой памяти ардуину на них натягиваю.
Но, если плохая, то плохая.
Float тоже напрямую не сравнишь, все равно где-то на побайтовое придётся прыгнуть.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

rkit пишет:

Никакого "обычного ==" для структур нет.

Я, видимо, что-то упустил, но перегрузку операторов даже Си для мк должен поддерживать. Иначе какой это Си?...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Плохая идея.

В структуре могут быть "дырки" из-за выравнивания элементов. 

#pragma pack(push,1)    спасёт этого дурня. 

sadman41
Offline
Зарегистрирован: 19.10.2016

DetSimen пишет:

ЕвгенийП пишет:

Плохая идея.

В структуре могут быть "дырки" из-за выравнивания элементов. 

#pragma pack(push,1)    спасёт этого дурня. 


Это на ESP у меня плохо кончалось - MK в кору падал.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

sadman41 пишет:
Это на ESP у меня плохо кончалось - MK в кору падал.

на 32 или 8266?

8266 у мня есть, не заметил никаких косяков с этой прагмой, а ESP32 у мня нет, я их еще не заказывал на  пащюпать, проверить не могу.  :(((

Morroc
Offline
Зарегистрирован: 24.10.2016

ЕвгенийП пишет:

В структуре могут быть "дырки" из-за выравнивания элементов. В этих "дырках" лежит то, что и лежало - т.е. грязь. А memcmp пофиг - если грязь разная, то она и структуры разными обзовёт.

А если "шлифануть" нулями (напрямую побайтно) после создания экземпляров есть шанс, что туда мусор попадет ? Так то вариант сравнения неплохой вроде.

sadman41
Offline
Зарегистрирован: 19.10.2016

DetSimen пишет:

sadman41 пишет:
Это на ESP у меня плохо кончалось - MK в кору падал.

на 32 или 8266?

8266 у мня есть, не заметил никаких косяков с этой прагмой, а ESP32 у мня нет, я их еще не заказывал на  пащюпать, проверить не могу.  :(((

https://arduino.ru/forum/programmirovanie/kod-krashit-esp8266

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:
На восьмибитной архитектуре вроде без дырок?
Если честно, не знаю. Но, даже если и так, то, во-первых, не стоит к такому привыкать, а во-вторых, дырки - они ведь не только из-за выравнивания бывают. Например, дырки вполне себе образуются на любой архитектуре при использовании битовых полей.

Я тут немного поговнокодил, посмотрите. Разместил две структуры в стеке. Одну до того, как слегка загадил стек, а другую - после. Так вот моё "загаживание" как раз попало в дырку и не дало структурам сравниться.

Затем, я воспользовался тупым присваиванием для структур - и вот тут-то они сравнились :-)

Так что, в этом говнокоде прекрасно всё :-)

#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) {}

Согласитесь, гораздо проще так не писать, чем потом искать такие ошибки :-)

sadman41
Offline
Зарегистрирован: 19.10.2016

Не спорю. Но как правильно сравнить float?

Относительно первопостовой задачи, пожалуй, стоит хранить несколько экземпляров с CRC ? Где оно не совпало, там и проблема.

rkit
Offline
Зарегистрирован: 23.11.2016

sadman41 пишет:
Не спорю. Но как правильно сравнить float?

abs(a - b) < 0.0001

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

sadman41 пишет:
Не спорю. Но как правильно сравнить float?

abs(a - b) < 0.0001

float a = 1.0e-12;

float b = 9.9e-12;

rkit
Offline
Зарегистрирован: 23.11.2016

И?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Я так понял, равны?

rkit
Offline
Зарегистрирован: 23.11.2016

В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

rkit пишет:

В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.

Вопрос был, как сравнивать float. И вдруг, откуда ни возьмись, появляется какая-то задача.

Не нужно плодить сущности.

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

rkit пишет:

В пределах данного допуска - да. Допуск можно задать любой в соответствии с задачей, если сам не догадался.

Вопрос был, как сравнивать float. И вдруг, откуда ни возьмись, появляется какая-то задача.

Не нужно плодить сущности.

Ну замени "...в соответствии с задачей" на "...в соответствии с допустимым отклонением" (#27)

или округляй обе величины и после этого уже сравнивай.

 

Этот прикол часто в экселе вылезает и пугает 1с-бухгалтерш.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

SLKH пишет:

или округляй обе величины и после этого уже сравнивай.

0.500000000000000000001

0.499999999999999999999

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Андриано! В данном случае я тебя не понимаю. Ркит фактически написал, что побитовое или абсолютное сравнение для float не имеет математического смысла (вне контекста задачи). Да, так и есть. Я не могу понять твою позицию. Мог бы ты её озвучить?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.

А если уж и изобретать что-либо универсально, оно никогда не окажется простым.

Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

SLKH пишет:

или округляй обе величины и после этого уже сравнивай.

0.500000000000000000001

0.499999999999999999999

1.  0.5==0.5

2. Ты не слишком ли много нулей с девятками наставил? float в ардуинстве пишется в 4 байта, это примерно 7 знаков на всё про всё.

 

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.

Примерно это rkit написал в #31.

На практике можно написать себе какую-нибудь функцию boolean equalFloat() по своему вкусу и втыкать её в большинство своих проектов. А в меньшинство с какими-нибудь астрономическими вычислениями не втыкать, сочинять что-то другое.

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.

А если уж и изобретать что-либо универсально, оно никогда не окажется простым.

Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.

Допускать разницу в младших битах мантиссы - вот и относительность.

SLKH
Offline
Зарегистрирован: 17.08.2015

del

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

SLKH пишет:

Допускать разницу в младших битах мантиссы - вот и относительность.

С младшими битами мантиссы - хорошая идея, я о ней думал, но проблема в том, что даже у достаточно близких (согласно выбранным критериям относительной точности) чисел могут различаться не только младшие, но даже старшие биты мантиссы. Пример был несколькими сообщениями назад.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

SLKH пишет:

andriano пишет:

SLKH пишет:

или округляй обе величины и после этого уже сравнивай.

0.500000000000000000001

0.499999999999999999999

1.  0.5==0.5

1 == 0 ?

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

SLKH пишет:

andriano пишет:

SLKH пишет:

или округляй обе величины и после этого уже сравнивай.

0.500000000000000000001

0.499999999999999999999

1.  0.5==0.5

1 == 0 ?

Нет. 0,500000 == 0,500000

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

Я считаю, что простых и универсальных способов сравнения вещественных чисел не существует.

А если уж и изобретать что-либо универсально, оно никогда не окажется простым.

Если уж брать что-то за основу, то в сравнении должны принимать участие не абсолютные числа, а относительные. Что-то вроде abs(a - b)/(abs(a) + abs(b)) < 0.0001. Или, дабы избежать деления на 0: abs(a - b) < (abs(a) + abs(b))*0.0001. Но, думаю, и здесь можно привести контраргументы.

abs(a-b) < abs(a)/10000 

SLKH
Offline
Зарегистрирован: 17.08.2015

andriano пишет:

SLKH пишет:

Допускать разницу в младших битах мантиссы - вот и относительность.

С младшими битами мантиссы - хорошая идея, я о ней думал, но проблема в том, что даже у достаточно близких (согласно выбранным критериям относительной точности) чисел могут различаться не только младшие, но даже старшие биты мантиссы. Пример был несколькими сообщениями назад.

Пух напишет класс для перекодировки мантиссы в код Грея.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пипец, мужики. Вроде ж, понедельник уже на дворе.

sadman41
Offline
Зарегистрирован: 19.10.2016

Вопрос же не про сравнение абстрактных float, где можно плюс-минус валенок допустить, а о сравнении считанных с трех мест хранения, при котором эти float должны быть эквивалентны. В противном случае определить сбой чтения/записи одного из трёх экземпляров наврядли возможно.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:
Вопрос же не про сравнение абстрактных float, где можно плюс-минус валенок допустить, а о сравнении считанных с трех мест хранения, при котором эти float должны быть эквивалентны. В противном случае определить сбой чтения/записи одного из трёх экземпляров наврядли возможно.

В таком случае float ничем не отличается от любого другого типа данных - только побитное совпадение.