Работа с инкрементом/декрементом
- Войдите на сайт для отправки комментариев
Сб, 11/05/2019 - 15:08
Всем привет! Есть такой код:
void loop() { Serial.print("Reading: "); Serial.print(scale.get_units(), 1); Serial.print(" r"); Serial.println(); if (scale.get_units() > 100) { level--; } else if (scale.get_units() < 60) { level++; } else { int level = 180; } }
Здесь нужно задать пределы инкрементирования и декрементирования как 0 и 240 соответственно. Т.е. чтобы level инкрементировался, но доходя до 240 останавливался бы на этом значении. Так же и с декрементом - чтобы level не уходил ниже нуля. Как это можно лучше сделать?
Как это можно лучше сделать?
Составить нормальный алгоритм и по нему написать программу. Ваша программа не выдерживает даже минимальной критики. Сотрите и напишите по новой согласно алгоритму.
Не правильно написал: "Здесь нужно задать пределы инкрементирования и декрементирования как 240 и 0 соответственно." - это верно.
mykaida,
А есть возможность ограничить инкрементирование каким-то пределом?
mykaida,
А есть возможность ограничить инкрементирование каким-то пределом?
Можно
if(level>240) level=240;
mykaida,
А есть возможность ограничить инкрементирование каким-то пределом?
Можно
if(level>240) level=240;
что мешает просто не допускать инкремента больше 240, чем делать и сбрасывать его?
что мешает просто не допускать инкремента больше 240, чем делать и сбрасывать его?
В данном случае, сэр, я пошел на поводу наглядности. Конечно можно и так:
Вместо
пишем что-то вроде
(применительно к коду из исходного сообщения)
level += level < 240;
"В моем доме попрошу такие слова не произносить!"
Действительно в Вашем доме?
Тогда приношу свои извенения.
Хочу лишь отметить, что предложенный вариант не имеет тех недостатков, которые присущи вариантам, опубликованным ранее, в частности:
- нет лишнего ветвления по сравнению с вариантом в сообщении №4,
- невозможен побочный эффект из-за сокращения количества вызовов метода класса как в сообщении №6.
- нет лишнего ветвления по сравнению с вариантом в сообщении №4,
Компилятор сгенерирует asm-код тоже без джампа по условию (просто интересно)?
Спасибо всем за ответы
Вместо
пишем что-то вроде
(применительно к коду из исходного сообщения)
andriano,
Мне понравился ваш вариант. Он работает.
Интересно узнать об операторе +=, я прочитал, что он имеет такой смысл:
A+=B эквивалентно A = A + B.
У нас, получается, level = level + level. Т.к. A = B = level. Почему же в итоге происходит именно инкрементирование? Как в данном случае работает += оператор?
A+=B эквивалентно A = A + B.
У нас, получается, level = level + level. Т.к. A = B = level. Почему же в итоге происходит именно инкрементирование? Как в данном случае работает =+ оператор?
нет, у нас получается level = level + условие
где условие = level < 240, оно либо истина (1), либо ложь(0), подставляем это в строку выше.
andriano - для "Песочницы" ваш код имеет один важный недостаток - новички его совершенно не понимают :)
Мне понравился ваш вариант. Он работает.
Интересно узнать об операторе +=, я прочитал, что он имеет такой смысл:
A+=B эквивалентно A = A + B.
У нас, получается, level = level + level. Т.к. A = B = level. Почему же в итоге происходит именно инкрементирование? Как в данном случае работает += оператор?
Вот этого я и хотел избежать. Пусть молодеж сначала программировать научится с помощью условных операторов, а уж потом применяет конструкты си. Но мы умные!
xDriver,
Спасибо :) Понятно, получается, тут как бы выполнение условия (true (1)) - является инкрементом.
итого у нас три предложения (пока)
1)
2)
3)
надо у ТС спросить что ему понятнее.
1.1)
не, ну енто вариации на тему :)
1.2)
Господа, да похрен как написать. Главное чтобы у программиста в башке был алгоритм и он его переводил на язык программирования. Оптимально - неоптимально это с опытом приходит. Мы можем 100500 раз стебаться над копирастерами, но если человек хочет разобраться, а не "памагите слить два кода" - я помогу. Но так, чтобы он прочувствовал и понял, чтобы он знал, что каждая строчка его программы делает. Не выдержит - не программист :)
Вместо
пишем что-то вроде
(применительно к коду из исходного сообщения)
Простите, я совсем не программист 500 уровня и я не понимаю в какой момент программа в данном выражении ограничит значение level уровнем 240. Чисто с точки зрения оператора += Если эта конструкция работает, то получается что сначала выполняется сравнение, а потом инкремент? Т. Е. Для начинающего, с учётом ассоциативности разбора cправа на лево эта строка должна выглядеть как level+=(level<240)? И придёт к виду if(levеl<240)level++; При не выполнении условия += будет проигнорирован? В чем будет разница в коде ассемблера? Есть ли выигрыш в такой нотации?
Вот. Век живи, век учись... Чтой то боюсь я такого продвинутого программирования.
Украдено до нас?
http://arduino.ru/Reference/Constrain
итого у нас три предложения (пока)
Да, там ещё можно придумать, делов-то
и это не предел.
andriano - для "Песочницы" ваш код имеет один важный недостаток - новички его совершенно не понимают :)
Это не бага, это - фича!
Конструкция достаточно короткая, чтобы новичек ее не испугался и попытался все-таки разобраться в ней. А когда разберется, думаю, будет для него от этого польза.
Но по большому счету - да: конструкция требует понимания достаточно фундаментальных вещей таких как Булева алгебра и особенности ее применения в Си. Поэтому думаю, что не только для новичков, но и для некоторых программистов, имеющих опыт, эта консрукция может оказаться интересной.
Почти так.
Для начала нужно запомнить или записать для себя таблицу определяющую приоритеты операций, чтоб скобками не злоупотреблять.
Операция += имеет более низкий приоритет чем операция сравнения <
таким образом сначала буден получен результат операции сравнения, тип которого - логический true/false
после этого будет выполнена операция += для заданного типа, в данном случае целочисленный, параметр для операции += полученный из предыдущего вычисления т.е. true/false
фактически получаем level += 1 или level += 0
и выполнение или не выполнение условия не проверяется, просто к переменной добавляется результат предыдущей операции
Женя! Поправь меня, если я не прав. Мне казалось, что а стандарте "истина" это "не ноль", а не конкретно 1. Поэтому не уверен, что неявное преобразование выдаст именно 1, а не то, что компилятору удобнее в текущий момент.
О! Я то как то не понял сразу что меня коробило. Я когда то ковырял код после hi-tech С компилятора PIC и там истина была 0хff. С тех пор как то в голове не лежит что 1=1 в булевой алгебре микроконтроллера равно 1.
В стандарте C99 раздел 7.16 Boolean type and values пункт 3.
true which expands to the integer constant 1,
false which expands to the integer constant 0,
and __bool_true_false_are_defined which expands to the integer constant 1.
кроме этого в пункте 4 сказано
Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then
redefine the macros bool, true, and false.
7.1.3 - это положения о зарезервированных идентификаторах
Значит если не перегружен true то должна быть единица.
wdrakula, нет, так было в С на самой заре времён. Сегодня чуть по-другому, но я не зря там сделал оговорку "в С ещё куда ни шло", разница между С и С++ есть и существенная.
Т.е. здесь в Си никакого преобразования типов не выполняется, т.к. результат сравнения уже имеет тип int: 0 или 1 (знаковый, кстати!)
А вот с С++ посложнее.
Т.е. здесь выражение andriano требует преобразования типа из bool в int. Правило преобразования таково:
Т.е. как бы результат-то получится верный. Но рекоммендовать выражение со скрытым преобразованием новичкам в качестве примера от которого им будет польза .... по мне, так сомнительно.
В стандарте C99 раздел 7.16 Boolean type and values пункт 3.
Пример неудачен по двум причинам.
1. Действующий стандарт С не 99, а 18.
2. Причём тут преобразование "Boolean type", если результат операций ">", "<" и т.п. в Си вовсе не boolean, а int. Так что в С никакого преобразование просто не выполняется.
Вот. Век живи, век учись... Чтой то боюсь я такого продвинутого программирования.
Для меня, например, сложение "integer + boolean" без особой на то необходимости представляется неким извращением. Впрочем, насколько я понимаю, в этом языке понятие стыда отсутствует полностью...
Для меня, например, сложение "integer + boolean" без особой на то необходимости представляется неким извращением.
Это вы ещё не видели операции сложения денежных сумм, записанных прописью с указанием дебетовая сумма или кредитовая:)
А что при конвертации int to bool? Я правильно понимаю, что ноль конвертируется в ноль (false), а всё остальное (любого знака) в единицу (true)?
Здесь похоже как раз справедливо - истина это всё, что не ноль.
Для меня, например, сложение "integer + boolean" без особой на то необходимости представляется неким извращением. Впрочем, насколько я понимаю, в этом языке понятие стыда отсутствует полностью...
Тут полностью поддерживаю.
Но Си - он такой, тут уж никуда не денешься.
А что при конвертации int to bool? Я правильно понимаю, что ноль конвертируется в ноль (false), а всё остальное (любого знака) в единицу (true)?
Здесь похоже как раз справедливо - истина это всё, что не ноль.
Да, например, способ превратить ненулевое число в единицу: MyNumber = !!MyNumber;.
А с объектным-то кодом что - будет он короче, если if() фактически занести в формулу или это просто красиво?
1. Действующий стандарт С не 99, а 18.
Ну тогда уж 11-й ;)
Для ардуино-иде 1.8.9 при выборе платы uno у avr-g++ вижу ключ -std=gnu++11 разве это не явное указание включения расширений стандарта
2. Причём тут преобразование "Boolean type", если результат операций ">", "<" и т.п. в Си вовсе не boolean, а int. Так что в С никакого преобразование просто не выполняется.
А что при конвертации int to bool? Я правильно понимаю, что ноль конвертируется в ноль (false), а всё остальное (любого знака) в единицу (true)?
Что мешает прочитать прямую цитату из стандарта в посте #30? Последний из сдвинутых вправо абзацев?
Почти так.
Для начала нужно запомнить или записать для себя таблицу определяющую приоритеты операций, чтоб скобками не злоупотреблять.
Операция += имеет более низкий приоритет чем операция сравнения <
таким образом сначала буден получен результат операции сравнения, тип которого - логический true/false
после этого будет выполнена операция += для заданного типа, в данном случае целочисленный, параметр для операции += полученный из предыдущего вычисления т.е. true/false
фактически получаем level += 1 или level += 0
и выполнение или не выполнение условия не проверяется, просто к переменной добавляется результат предыдущей операции
Смотрю я на строку из соседней ветки:
if
(tim[i] - 500 < millis() - last_time[i])
через полсекунды после включения ардуины и далее она будет эквивалентна
"
if
(tim[i] - 1 - last_time[i])" ?
через полсекунды после включения ардуины и далее она будет эквивалентна "if (tim[i] - 1 - last_time[i])" ?
сложение и вычитание - приоритет 6
операции сравнения < ≤ > ≥ - приоритет 8
значит сначала выполняется tim[i] - 500 и millis() - last_time[i]
затем операция сравнения <
Вывод:
Это вы ещё не видели операции сложения денежных сумм, записанных прописью с указанием дебетовая сумма или кредитовая:)
Тихонов-Козлов?
А, ну да. Всё ясно как божий день.)))
А если по простому, то в данном случае, без if-а короче на 2 байта.
1. Действующий стандарт С не 99, а 18.
Ну тогда уж 11-й ;)
Что-то мне подсказывает, что Вы Си и Си++ путаете :)
А если по простому, то в данном случае, без if-а короче на 2 байта.
Наверняка эти два байта будут сожраны, если делать с "защитой" через value += !!(condition). Так что только буковки исходника экономятся и то в случае шага равному единице.
Буковки экономятся, понимание усложняется... Для данного компилятора защита !! не нужна. Для наглядности.
Я когда то ковырял код после hi-tech С компилятора PIC и там истина была 0хff. С тех пор как то в голове не лежит что 1=1 в булевой алгебре микроконтроллера равно 1.
Какая версия htpicc?