Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Способы проверки диапазона для целого числа


Автор: zim22 25.6.2009, 18:52
Читаю "Совершенный Код" Макконнелла
Не хочу соглашаться с ним в этом совете:
Упорядочение числовых выражений в соответствии со значениями на числовой прямой
в двух словах - его смысл в том, что необходимо слева от знака сравнения ставить константное число (к примеру), а неизвестную - справа.
т.е. так:
Код

if (0 < x && 10 > x)

проблема в том, что моему мозгу сложно понять это выражение smile 
чтобы его осмыслить, я разбираю это выражение за 3 шага:
Код

1) если 0 < x, значит x >= 0
2) если 10 > x, значит x <= 10 
3) если x >= 0 И x <= 10, то x находится в диапазоне от 0 до 10


если бы выражение в самом начале было записано как
Код

if (x >= 0 && x <= 10)

то мне не пришлось бы выполнять 1 и 2 шаг. Я сразу бы "осознал" допустимый диапазон для x.

в каком стиле вы предпочитаете писать логические условия? какой случай вам легче понять? согласны ли вы с Макконнелом? smile

текст совета Макконнелла:
Цитата

Организуйте числовые условия так, чтобы они соответствовали порядку точек на числовой прямой. В общем случае структурируйте выражений так, чтобы сравнения выглядели следующим образом:

MIN_ELEMENT <= i and i <= MAX_ELEMENT
i < MIN_ELEMENTS or MAX_ELEMENTS < i

Идея в том, чтобы расположить элементы по порядку слева направо, от наименьших к наибольшим. В первой строке MIN_ELEMENTS и MAX_ELEMENTS - это две граничные точки, и поэтому они расположены по краям выражения. Подразумевается, что переменная i должна находиться между ними, и поэтому она расположена в середине. Во втором примере вы проверяете, находился ли i вне диапазона, поэтому i расположена по краям условия, а MIN_ELEMENTS и MAX_ELEMENTS - посредине. Этот подход позволяет легко создать визуальное представление сравнения:
http://xmages.net/show.php/295825_df.gif.html
Если вы сравниваете значение i только с MIN_ELEMENTS, то расположение i зависит от того, каким должно быть i в случае успешной проверки условия. Если предполагается, что i меньше, то условие выглядит так:
Код

while (i < MIN_ELEMENTS) ...

Но если i должно быть больше, вы получаете:
Код

while ( MIN_ELEMENTS < i) ...

Этот подход более очевиден, чем такие условия, как:
Код

(i > MIN_ELEMENTS) and (i < MAX_ELEMENTS)

которые не позволяют читателю визуализировать проверяемое выражение.


Цитата

Этот подход более очевиден,

не для меня...

Автор: Andrew121 25.6.2009, 19:17
Цитата(zim22 @  25.6.2009,  18:52 Найти цитируемый пост)
моему мозгу сложно понять это выражение

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

Автор: UnrealMan 25.6.2009, 19:22
Цитата(zim22 @  25.6.2009,  18:52 Найти цитируемый пост)
1) если 0 < x, значит x >= 0
2) если 10 > x, значит x <= 10 

А зачем к нестрогим неравенствам приводить?

Автор: GoldFinch 25.6.2009, 19:28
Цитата(Andrew121 @  25.6.2009,  20:17 Найти цитируемый пост)
чаще всего в коде батаников/зазубриков.

и еще людей, знающих что такое числовая ось.
а ты видимо не знаешь.

Автор: Andrew121 25.6.2009, 19:39
Цитата(GoldFinch @  25.6.2009,  19:28 Найти цитируемый пост)
и еще людей, знающих что такое числовая ось.

Спасибо. Дополню.


Цитата(GoldFinch @  25.6.2009,  19:28 Найти цитируемый пост)
а ты видимо не знаешь. 

 smile 

Автор: zim22 25.6.2009, 20:00
Цитата(UnrealMan @  25.6.2009,  19:22 Найти цитируемый пост)
А зачем к нестрогим неравенствам приводить?

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

10 > x => x <= 10
20 <= x => x > 20

я ошибался.  smile 

Автор: Леопольд 25.6.2009, 20:00
Цитата(zim22 @ 25.6.2009,  18:52)
Читаю "Совершенный Код" Макконнелла
Не хочу соглашаться с ним в этом совете:
Упорядочение числовых выражений в соответствии со значениями на числовой прямой
в двух словах - его смысл в том, что необходимо слева от знака сравнения ставить константное число (к примеру), а неизвестную - справа.
т.е. так:
Код

if (0 < x && 10 > x)

проблема в том, что моему мозгу сложно понять это выражение smile
...

Цитата(Макконнелл)

...
MIN_ELEMENT <= i and i <= MAX_ELEMENT
i < MIN_ELEMENTS or MAX_ELEMENTS < i


Вам не кажется что он имел ввиду вот это?
Код

if (0 < x && x < 10)
...
if (x < 0 || 10 < x)

Вполне понятно и не надо делать финт ушами. Но я предпочитаю так же как и Вы:
Код

if (x => 0 && x <= 10)

Хотя на самом деле мне одинаково понятно, что так, что эдак. Так что "по барабану"...

Автор: zim22 25.6.2009, 20:09
Цитата(Леопольд @  25.6.2009,  20:00 Найти цитируемый пост)
Вам не кажется что он имел ввиду вот это?
Код

if (x < 0 && 10 < x)


вы имели ввиду это?
Код

i < MIN_ELEMENTS or MAX_ELEMENTS < i

там было ИЛИ, а не И.
И быть не может smile
***
избавившись от заблуждения
Цитата(zim22 @  25.6.2009,  20:00 Найти цитируемый пост)
при инвертировании операндов в логическом условии необходимо добавлять или отнимать знак равенства

уже проще в голове держать условие!  smile 
***
но всё-равно, интересно узнать, практикуете ли вы в коде выравнивание по числовой прямой?



Автор: kemiisto 25.6.2009, 20:10
Цитата(zim22 @  25.6.2009,  18:00 Найти цитируемый пост)
у меня было предубеждение, что при инвертировании операндов в логическом условии необходимо добавлять или отнимать знак равенства

Это плохо. Незнание таких элементарных вещей... И поэтому, дальше, как отметил Леопольд, Вы ошиблись.
Цитата(Леопольд @  25.6.2009,  18:00 Найти цитируемый пост)
Вам не кажется что он имел ввиду вот это?
Код
if (x < 0 && 10 < x)


Именно так и рекомендует автор. Неплохой, кстати, совет.

Добавлено через 2 минуты и 43 секунды
Цитата(zim22 @  25.6.2009,  18:09 Найти цитируемый пост)
там было ИЛИ, а не И.

zim22, у Вас в голове каша. Очень запущено. Там два разных случая по тексту. Первый - когда переменная принадлежит некому онранийченному замкнутому отрезок и это MIN_ELEMENT <= i and i <= MAX_ELEMENT. Второй, наоборот, переменная лежит вне такого отрезка и это i < MIN_ELEMENTS or MAX_ELEMENTS < i.

Добавлено через 4 минуты и 16 секунд
А понял! Леопольд тоже ошибся. Там or надо, а не and. А иначе бессмыслица.

Автор: Леопольд 25.6.2009, 20:15
Цитата(zim22 @ 25.6.2009,  20:09)

там было ИЛИ, а не И.
И быть не может smile

Опс... Не успел поправить... smile Надо сначала перечитывать, что написал, и только потом постить. Темка-то, "горячая" оказалась smile

Добавлено через 4 минуты и 16 секунд
Цитата(zim22 @ 25.6.2009,  20:09)
но всё-равно, интересно узнать, практикуете ли вы в коде выравнивание по числовой прямой?

Нет.
Даже не задумывался. А что, есть какие-то серьёзные выгоды, кроме красоты? smile
Вот от паттернов проектирования выгоды весьма существенны...

Автор: zim22 25.6.2009, 20:26
Цитата(kemiisto @  25.6.2009,  20:10 Найти цитируемый пост)
Там два разных случая по тексту

я понял эти два случая, спасибо.


Цитата(kemiisto @  25.6.2009,  20:10 Найти цитируемый пост)
И поэтому, дальше, как отметил Леопольд, Вы ошиблись.

не соглашусь. Леопольд ошибся.
Цитата

Вам не кажется что он имел ввиду вот это?
Код

if (x < 0 && 10 < x)



если конвертировать выражение в "понятный" для меня вид, то получим это:
Код

if (x < 0 && x > 10)

скажите, как может x быть меньше нуля и одновременно больше 10?
***
Цитата(Леопольд @  25.6.2009,  20:15 Найти цитируемый пост)
А что, есть какие-то серьёзные выгоды, кроме красоты?

я думаю, если команда разработчиков включит эту рекомендацию в свои стандарты кодирования - будет меньше неразберихи в логических условиях и код будет быстрей читаться.
***
Цитата(Andrew121 @  25.6.2009,  19:17 Найти цитируемый пост)
Как правило, такой вид записи, наблюдаю чаще всего в коде батаников... Так как опыт практического программирования у них крайне мал.

может быть наоборот: практический опыт у них очень большой? smile

Автор: kemiisto 25.6.2009, 20:46
Цитата(zim22 @  25.6.2009,  18:26 Найти цитируемый пост)
не соглашусь. Леопольд ошибся.

Ага. smile Я тоже уже заметил. Пост править не стал. История как-никак. smile 

Цитата(zim22 @  25.6.2009,  18:26 Найти цитируемый пост)
если конвертировать выражение в "понятный" для меня вид, то получим это:

zim22, отбросим на секунду, то что в примере Леопольда будет пустое множество значений. Что понятнее:
  • a < x && x < b;
  • a < x && b > x;
  • x > a && x < b;
  • ...
?
Первый вариант. Ибо не надо дополнительных усилий, чтобы преобразовать его в двойное неравенство. А мы именно это математичсекую запись пытаемся закодировать. И с примером с or тоже самое. Этот ваш Макконнелл об этом и говорит.

Автор: GoldFinch 25.6.2009, 20:51
zim22, поправь подпись, он Де Морган, а не "Деморган"

Автор: zim22 25.6.2009, 21:19
Цитата(kemiisto @  25.6.2009,  20:46 Найти цитируемый пост)
Первый вариант. Ибо не надо дополнительных усилий, чтобы преобразовать его в двойное неравенство

преобразование в двойное неравенство - это преобразование Де Моргана что-ли?
мне никаких усилий не нужно, чтобы преобразовать любое логическое условие с двумя операндами и оператором ИЛИ или И.
очень просто делается: отрицаем каждый операнд, меняем знак между операндами (И <=> ИЛИ) и отрицаем всё выражение.
***
Цитата(kemiisto @  25.6.2009,  20:10 Найти цитируемый пост)
Это плохо. Незнание таких элементарных вещей... 

я понял, откуда было моё заблуждение! я не различал между собой два случая:
1) отрицание логического выражения
2) перестановка операндов в логическом выражении с левой стороны на правую от знака операнда

т.е. если мы отрицаем логическое условие, то я правильно тогда предполагал. < меняется на >=, > на <=
возьмём к примеру это:
Код

if (a > b) { cout << "true"; }

отрицаем и получаем:
Код

if (!(a > b)) { cout << "false"; }

что равнозначно варианту:
Код

if (a <= b) { cout << "false"; }

т.е. > меняется на <= smile
***
Цитата

a < x && x < b;

Я придумал, как визуализировать такие выражения. Представлять у себя в голове прямоугольнички разного размера. 
1) a < x
    два прямоугольника. a маленький. x большой
2)x < b
    ещё один прямоугольник представляю. самый большой. b
что дальше с ними делать - не знаю smile

http://xmages.net/show.php/296059_bb.gif.html
 smile 
Цитата(GoldFinch @  25.6.2009,  20:51 Найти цитируемый пост)
поправь подпись, он Де Морган, а не "Деморган"

поправил. хотя фамилию  я не с головы придумал.  в книжечке Совершенный Код он был написан именно как Деморган. Но корявый русский перевод мог иметь место.

Автор: kemiisto 25.6.2009, 21:26
Цитата(zim22 @  25.6.2009,  19:19 Найти цитируемый пост)
преобразование в двойное неравенство - это преобразование Де Моргана что-ли?

Да нет. smile Вот, смотрите. Есть 2 неравенства: x > a и x < b. Теперь, если потребовать одновременного выполнения обоих условий, то получим двойное неравенство a < x < b. Его так принято записывать. Теперь вы видите, что ближайщий вариант в коде, a < x && x < b. Элементарная логика, де Морган (кстати, он таки де Морган) тут не причём. smile 

Автор: zim22 25.6.2009, 21:41
Цитата(kemiisto @  25.6.2009,  21:26 Найти цитируемый пост)
то получим двойное неравенство a < x < b. Его так принято записывать

теперь понятно, что вы имели ввиду  smile 

Автор: baldina 26.6.2009, 02:13
Макконнелла, признаюсь, не читал, но всю жизнь пишу
Код

a < x && x < b

именно из тех соображений, что приводит kemiisto: это наиболее близко к привычному a < x < b

Добавлено через 1 минуту и 33 секунды
 smile возможно, это привычно тем, для кого "числовая ось" - не ругательство?  smile 

Автор: Леопольд 26.6.2009, 08:36
Цитата(zim22 @ 25.6.2009,  20:26)
Цитата(kemiisto @  25.6.2009,  20:10 Найти цитируемый пост)
И поэтому, дальше, как отметил Леопольд, Вы ошиблись.

не соглашусь. Леопольд ошибся.
Цитата

Вам не кажется что он имел ввиду вот это?
Код

if (x < 0 && 10 < x)



если конвертировать выражение в "понятный" для меня вид, то получим это:
Код

if (x < 0 && x > 10)

скажите, как может x быть меньше нуля и одновременно больше 10?
***

Я исправил её почти сразу после того как запостил... Или это уже не имеет значения? smile Вроде бы ошибка настолько очевидна, что понятно и так что именно имелось ввиду... Конечно же if (x < 0 || 10 < x)

Цитата(zim22 @ 25.6.2009,  20:26)
Цитата(kemiisto @  25.6.2009,  20:10 Найти цитируемый пост)

Цитата(Леопольд @  25.6.2009,  20:15 Найти цитируемый пост)
А что, есть какие-то серьёзные выгоды, кроме красоты?

я думаю, если команда разработчиков включит эту рекомендацию в свои стандарты кодирования - будет меньше неразберихи в логических условиях и код будет быстрей читаться.
***


Вообще очень хорошо смотрится 
Код

if(a < x && x < y && y < z && z < b){
 так что соглашусь полностью. Почитать, что ли, Макконела... smile

Цитата(zim22 @ 26.6.2009, 08:42)

расшифруйте. у "to fill" миллион вариантов перевода smile

to fill - заполнить 
У меня дурная привычка, сначала запостить, потом минут 15 править ошибки, нет бы наоборот... smile

Автор: zim22 26.6.2009, 08:42
Цитата(Леопольд @  26.6.2009,  08:36 Найти цитируемый пост)
to fill

расшифруйте. у "to fill" миллион вариантов перевода smile
***
Цитата(Леопольд @  26.6.2009,  08:36 Найти цитируемый пост)
Почитать, что ли, Макконела...

книжка тяжёлая (1.5 кг). если по голове ударить - убить можно smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)