сравнение во временной последовательности
В скетче Arduino пользователю предлагается ввести число, представляющее время в формате ЧЧ:ММ. Это число должно быть добавлено в конец упорядоченной и ограниченной последовательности времен.
--первый ввод (нижний предел) может быть в любое время в течение 24 часов,
--верхний предел рассчитывается как нижний_предел+период; период может быть 1, 2, 3, 4, 6, 8, 12 или 24 часа,
--а чтобы быть принятым, входные данные должны соответствовать хронологическому положению предыдущего элемента и находиться в пределах заданного периода;
Например, если первый элемент — 20:00, а период — 8, то верхний предел будет 20+8=28, что составляет 04:00; принимаются значения 21:00 и 03:00, а значения 19:00, 05:00, 09:00, 17:00, ... отклоняются.
Без какой-либо информации о «дне» я не нашел подходящего алгоритма, и ни одна из доступных библиотек Arduino в этом случае не пригодится.
любая ссылка или подсказка,...
@moyoumos, 👍0
Обсуждение1 ответ
Лучший ответ:
Вот основная идея и пример реализации решения проблемы:
Проблема заключается в следующем: если задано начальное время time1 и период period, каждый из которых описывается парой (час,минута), как можно проверить, находится ли другое время time2 в пределах от time1 до time1 + period?
Во-первых, мы видим, что, имея пару (час, минута), мы можем вычислить общее количество минут как totalMinutes = 60*час + минута.
Затем мы можем заметить, что есть два отдельных случая, которые мы должны проверить:
- Весь «период проверки времени», то есть от
time1доtime1 + period, находится в диапазоне от00:00до24:00без выхода за пределы24:00при простом сложении времени. Тогда мы можем использовать простую проверку границ, сформулированную как «time2должно быть большеtime1и меньше или равноtime1 + periodпри сравнении общего количества минут». time1 + periodпереполняется после24:00. Рассмотрим примерtime1 = 20:00иperiod = 8:00. Таким образом, все допустимые значения времени находятся в диапазоне от20:00до04:00с неявным «циклическим переходом» от 24:00 до 00:00. Видим, что теперь необходимо проверить два временных интервала: всё с20:01до24:00и с00:00до04:00является допустимым. Таким образом, мы можем снова вывести границы в минутах. Мы можем получить04:00, вычислив20:00 + 08:00 по модулю 24:00. Оператор языка C%используется для вычисления остатка от деления на определённое число. Например,28 % 24 = 4, поскольку28 / 24 = 1 остаток 4. Это называется модульной арифметикой.
Следующая программа на C++ демонстрирует решение:
#include <cstdio>
/* returns whether time2 defined by hour2:minute2 is within the period time1 = hour1:minute1 to time1 + period. */
bool is_time_within_period(
int hour1, int minute1,
int hour2, int minute2,
int periodHour, int periodMinute) {
//Отклонить мусорный ввод
if(hour1 > 24 || hour2 > 24
|| minute1 > 60 || minute2 > 60
|| periodHour > 24 || periodMinute > 60) {
//TODO выдает сообщение об ошибке
return false;
}
//Переводим часы и минуты в абсолютные минуты. Один час равен 60 минутам.
int time1Minutes = 60 * hour1 + minute1;
int periodMinutes = 60 * periodHour + periodMinute;
int time2Minutes = 60 * hour2 + minute2;
int periodEnd = time1Minutes + periodMinutes;
//Если время начала плюс время периода превышают 24:00, то имеет место циклический переход, который необходимо учитывать.
bool wrapAround = false;
if( periodEnd > (24 * 60)) {
wrapAround = true;
}
bool result = false;
//printf("Перенос: %d Конец периода %d\n", wrapAround, periodEnd);
if(!wrapAround) {
//если нет циклического перехода, мы можем просто сравнить общее количество минут друг с другом
//время1 должно быть после времени2, но до (время1 + период).
result = time2Minutes <= (time1Minutes + periodMinutes) && time2Minutes > time1Minutes;
} else {
//Произошёл циклический переход, т.е. время начала + период вышли за пределы 24:00.
//Нам нужно сделать два сравнения: находится ли это в промежутке времени от time1Minutes до 24:00?
result = time1Minutes < time2Minutes && time2Minutes <= (24 * 60);
//результат также может быть приемлемым, если он находится в диапазоне от 00:00 до оставшегося периода
//Используйте оператор модуля. Это преобразует, например, 28:00 в 04:00 (по модулю 24 часа, вычисленного в минутах).
int upper = (periodEnd % (24 * 60));
//printf("Верхний: %d (%02d:%02d)\n", верхний, (верхний / 60), верхний % 60);
result |= time2Minutes >= 0 && time2Minutes <= upper;
}
return result;
}
int main() {
const int hourStart = 20;
const int minuteStart = 0;
const int periodHours = 8;
const int periodMinutes = 0;
//поиграйтесь с этими значениями
const int compareTimeHour = 4;
const int compareTimeMinute = 0;
printf("Start: %02d:%02d\n", hourStart, minuteStart);
printf("Period: %02d:%02d\n", periodHours, periodMinutes);
printf("Check time: %02d:%02d\n", compareTimeHour, compareTimeMinute);
bool res = is_time_within_period(hourStart, minuteStart, compareTimeHour, compareTimeMinute, periodHours, periodMinutes);
if(res) {
printf("Time is within bounds\n");
} else {
printf("Time is not within bounds\n");
}
printf("Hello\n");
return 0;
}
Функция is_time_within_period не имеет зависимостей и поэтому может быть скопирована и вставлена в любой скетч Arduino.
Пусть время начала будет 20:00, а период — 04:00. Тогда, если мы дадим программе разные значения времени для сравнения, мы увидим, что она действительно работает.
Start: 20:00
Period: 08:00
Check time: 20:00
Time is not within bounds
Start: 20:00
Period: 08:00
Check time: 20:01
Time is within bounds
Start: 20:00
Period: 08:00
Check time: 04:00
Time is within bounds
Start: 20:00
Period: 08:00
Check time: 04:01
Time is not within bounds
все было очень просто: если в интервале сравнения есть циклический переход, то мы делим этот интервал на два в точке этого цикла... спасибо и +5..., @moyoumos
Функция is_time_within_period не имеет зависимостей и поэтому может быть скопирована и вставлена в любой скетч Arduino., @moyoumos
- avrdude ser_open() can't set com-state
- Float печатается только 2 десятичных знака после запятой
- Как получить текущее время и дату в Arduino без внешнего источника?
- Как запустить цикл на определенное время?
- ошибка: espcomm_upload_mem failed при загрузке скетча
- Печать массива байтов на экране последовательного монитора Arduino IDE
- Разница между «time_t» и «DateTime»
- Почему мои часы реального времени показывают неверное время с моего ПК?
Вводятся ли числа через
Serial? Верно ли, что в первом примере будет принято любое время от20:01до04:00включительно?, @Maximilian GerhardtМне это напоминает домашнее задание..., @Majenko
Совет: работа занимает считанные минуты. Оператор деления по модулю (
%) — ваш лучший друг., @Majenko@maximilian-gerhardt: числа вводятся с помощью кнопок... принимаются любые числа от 20:01 до 04:00, если они находятся хронологически после последнего элемента перед верхним пределом..., @moyoumos
У вас тут множество проблем: как ввести время, как перевести это время в минуты, как правильно сравнить эти значения. Решайте задачи по одной за раз., @Majenko
Так вы сказали, что уже решили проблему?, @Maximilian Gerhardt
@majenko: извините, я не предоставил достаточно информации... единственная проблема в том, как правильно сравнивать эти времена..., @moyoumos
@maximilian-gerhardt: работа в минутах дает простое представление о времени, но не решает проблему... применительно к примеру верхний предел все еще меньше нижнего предела: [от 20:00 до 04:00] становится [от 1200 до 240]..., @moyoumos
if (start < end) { // проверить, больше ли оно начала *и* меньше ли конца } else { // проверить, больше ли оно начала *или* меньше ли конца }, @Majenko