Главная - Литература

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 [142] 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

Табл. 19-1. Преобразования логических переменных в соответствии с теоремами Деморгана

Исходное выражение

Эквивалентное выражение

not А and not В

not ( А or В )

not А and В

not ( А or not В )

А and not В

not ( not А or В )

А and В

not ( not A or not В )

not А or not В*

not ( A and В )

not А or В

not ( A and not В )

А or not В

not ( not A and В )

А or В

not ( not A and not В )

Это выражение и используется в примере.

Использование скобок для пояснения логических выражений

ШрИфШи»!! тлт Вртщы сложное логическое выражение, не надей-щытш скобок т ftW- порядок вычисления его операндов в языке програм-шт выражений мирования - используйте скобки, чтобы сделать ваши на-

ем, ь «Шсобки» мерения понятными. Скобки уменьшают требования, предъ-

щт являемые к читателю кода, который может и не разобрать-

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

Вот пример выражения, содержащего слишком мало скобок: Пример выражения, содержащего слишком мало скобок (Java)

if ( а < b == с d ) ...

Начнем с того, что это выражение слишком запутано. Оно тем более сбивает с толку что не ясно, хотел ли кодировщик проверить условие (a<b)==(c==d) или ( ( а< Ь) == с) == d. Следующая версия все равно не идеальна, но скобки все же помогают:

Пример выражения, частично улучшенного с помощью скобок (Java)

if ( ( а < b ) == ( с == d ) ) ...

В этом случае скобки повышают удобство чтения и корректность программы, поскольку компилятор не истолковал бы первый фрагмент таким способом. Когда сомневаетесь, используйте скобки.

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



ния слева направо. Встретив открывающую скобку скажите ирецртиаи ьшй Многие

«один». Каждый раз при встрече открывающей скобки уве- шттый редакторы, <шти-

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

шайте это число. Если к концу выражения у вас опять по- оредошшю! кошнды дяя

лучится О, то ваши скобки симметричны. птт парных крутш, квадратных и фйгурнш скобок.

пример симметричных скобок (Java) ГГГ

- Читаем это выражение. роеание* радела 30.t

->if ( ( ( а < b ) == ( с d ) ) && !done ) ...

Ill II II I

гО 1 2 3 2 3 2 1 О

- Произносим эти числа.

В этом примере в конце получился О, следовательно, скобки симметричны. В следующем примере количество отрывающих и закрывающих скобок не одинаково:

Пример несимметричных скобок (Java)

- Читаем это выражение.

->if ( ( а < b ) == ( с d ) ) && !done ) . ..

II II II I

гО 12 12 10 -1

- Произносим эти числа.

Значение О, полученное до последней закрывающей скобки, подсказывает, что где-то до этой точки была пропущена скобка. Вы не должны получить О, не достигнув последней скобки в выражении.

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

Понимание правил вычисления логических выражений

Множество языков содержит неявную управляющую форму, которая начинает действовать при вычислении логических выражений. Компиляторы некоторых языков вычисляют каждый элемент логического выражения перед объединением всех этих элементов и вычисления значения всего выражения. Компиляторы других используют «короткозамкнутый» (или «ленивый») алгоритм, обрабатывая только необходимые элементы выражения. Это особенно важно, когда в зависимости от результатов первой проверки вы можете не захотеть выполнять следующий тест. Допустим, вы проверяете элементы массива с помощью следующего выражения:

Пример псевдокода неправильной проверки условия

while ( i < MAX ELEMENTS and item[ i ] о 0 ) . . .

Если вычисляется выражение целиком, вы получите ошибку при последней итерации цикла. В этом случае переменная / равна maxElements, 2i значит, выражение itemf i] эквивалентно item[ maxElements у, что является недопустимым значением



индекса. Вы можете возразить, что это не имеет значения, поскольку вы только обращаетесь к элементу, а не изменяете его. Но это неряшество способно сбить с толку читателя вашего кода. Во многих средах этот код будет также генерировать ошибку выполнения или нарушение защиты.

Используя псевдокод, можно реструктурировать данное условие так, чтобы эта ошибка не возникала:

Пример псевдокода правильно реструктурированной проверки условия

while ( i < MAX ELEMENTS ) if ( item[ i ] о 0 ) then

Этот вариант корректен, так как item[ i] будет вычисляться, только когда / меньше, чем maxElements,

Многие современные языки предоставляют средства, которые изначально предотвращают возможность возникновения такой ошибки. Так, С++ использует корот-козамкнутые вычисления: если значение первого операнда в операции and ложно, то второй операнд не вычисляется, потому что полное выражение в любом случае будет ложным. Иначе говоря, в С++ единственный элемент выражения:

if ( SomethingFalse && SomeCondition ) ...

который будет вычисляться, - это SomethingFalse. Обработка выражения завершается, поскольку значение SomethingFalse определяется как ложное.

Аналогичное укороченное вычисление будет производиться и для оператора or. В С++ и Java в выражении:

if ( somethingTrue someCondition ) ...

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

Пример условия, которое работает благодаря короткозамкнутому вычислению (Java)

if ( ( denominator ! = О ) && ( ( item / denominator ) > MIN VALUE ) ) ...

Если бы это выражение вычислялось целиком, то в случае, когда переменная denominator равна О, операция деления во втором операнде генерировала бы ошибку деления на 0. Но поскольку вторая часть не вычисляется, если значение первой ложно, то когда denominator равен О, вторая операция не выполняется, и ошибка деления на О не возникает.

С другой стороны, из-за того что операция вв- (and) вычисляется слева направо, следующее логически эквивалентное выражение работать не будет:



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 [142] 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294



0.0023