Ответы на задачи 24 (С1)
Скачать 1.92 Mb.
|
if x > maximum then maximum := x;
а) неверное начальное значение переменной sum: Было: sum := 1; Исправление: sum := 0; б) неверное увеличение суммы Было: sum := sum + 1; Исправление: sum := sum + d;
а) неверное начальное значение переменной sum: Было: sum:= 1; Исправление: sum:= 0; б) неверное увеличение суммы Было: sum := d; Исправление: sum := sum + d;
Выполним трассировку для числа 15:
Самый сложный вопрос в этой задаче – второй (когда программа сработает верно). Как следует из трассировки, на каждом шаге отсекается одна десятичная цифра числа, поэтому это может быть только однозначное число. Для однозначного числа выполнится один шаг цикла, при этом счётчик будет увеличен на 1, если число нечётное, или останется равным 0, если число чётное. Чисел, которые содержат 0 цифр в двоичной системе нет, и есть только одно число – 1, – которое содержит одну цифру. Поэтому единственный правильный ответ:
Ошибок в программе две. Во-первых, когда мы считаем цифры двоичной записи, нужно отсекать цифры не в десятичной записи числа, а в двоичной. Поэтому делить нужно не на 10, а на 2. Во-вторых, при каждом отсечении нужно увеличивать счётчик ровно на 1.
а) неверное учеличение счётчика cnt: Было: cnt:=cnt + x mod 2; Исправление: cnt:=cnt + 1; б) неверное изменение переменной x: Было: x:=x div 10; Исправление: x:=x div 2;
Выполним трассировку для числа 6:
Самый сложный вопрос в этой задаче – второй (когда программа сработает верно). Как следует из трассировки, если введено чётное число, на первом же шаге значение x становится равно 0 (остатку от его деления на 2) и цикл завершается. При этом выводится значение 1. Если же вводится нечётное число, то значение x остаётся равным 1 и далее не изменяется, так что программа зацикливается. Таким образом, программа выводит правильный ответ для чётных чисел, которые содержат одну единицу в двоичной записи, то есть, для натуральных степеней числа 2: чисел 2, 4, 8, 16 и т.д.
Ошибок в программе две. Во-первых, когда мы считаем единицы двоичной записи, нужно отсекать цифры с помощью деления на 2, а не взятия остатка. Во-вторых, при каждом отсечении нужно увеличивать счётчик только тогда, когда остаток от деления (последняя цифра) равна 1.
а) неверное увеличение счётчика cnt: Было: cnt:=cnt + 1; Исправление: if x mod 2 = 1 then cnt:=cnt + 1; или так: Исправление: cnt:=cnt + x mod 2; б) неверное изменение переменной x: Было: x:=x mod 2; Исправление: x:=x div 2;
При вводе значения 0,4 условие s <= а неверно при входе в цикл, поэтому цикл не выполнится ни разу, и будет выведено значение k = 1:
Теперь выясним, когда программа выводит ответ 2. Это означает, что цикл выполнится ровно 1 раз, и переменная k увеличится с начального значения 1 до 2. Заметим, что для этого нужно, чтобы
Очевидно, что условия a) и б) не могут выполняться одновременно ни для какого A, поэтому
Займемся исправлением программы. Во-первых, заметим что в переменной s НЕ накапливается сумма, новое слагаемое нужно прибавлять к предыдущему значению s: s := s + 1.0 / k; Вторая ошибка более тонкая: в условии окончания цикла стоит нестрогое неравенство, поэтому в условии продолжения цикла должно стоять обратное условие – строгое равенство: s < a.
а) неверное условие цикла: Было: while s <= a do begin Исправление: while s < a do begin б) неверное изменение переменной s: Было: s:= 1.0/k; Исправление: s:= s + 1.0/k;
При вводе значения 1,4 условие s >= а неверно при входе в цикл, поэтому цикл не выполнится ни разу, и будет выведено значение k = 0:
Теперь выясним, когда программа выводит ответ 1. Это означает, что цикл выполнится ровно 1 раз, и переменная k увеличится с начального значения 0 до 1. Заметим, что для этого нужно, чтобы
Очевидно, что условия a) и б) не могут выполняться одновременно ни для какого A, поэтому
Займемся исправлением программы. Во-первых, заметим что начальное значение переменной s (где накапливается сумма) не равно нулю для k = 0, это первая ошибка, её нужно исправить: s := 0; Вторая ошибка – в условии. В заданном условии окончания цикла стоит нестрогое неравенство, поэтому в условии продолжения цикла должно стоять обратное условие – строгое равенство: s < a.
а) неверное начальное значение переменной s: Было: s:= 1; Исправление: s:= 0; б) неверное условие цикла: Было: while s >= a do begin Исправление: while s < a do begin Заметим, что ошибку а) можно исправить и по-другому: а) неверное начальное значение переменной k: Было: k:= 0; Исправление: k:= 1;
В цикле обнаруживаем оператор ввода read(x); который говорит о том, что в переменной x хранится последнее введённое число (а не счётчик неотрицательных чисел!). Это число обрабатывается условным оператором if x >= 0 then begin p := p*x; count := count+1 end Из этих строк следует, что переменная p накапливает произведение неотрицательных чисел, а переменная count – это счётчик неотрицательных чисел, который и нужно вывести на экран в конце программы. Сначала обе переменные обнуляются, поэтому значение p так и останется равным нулю (умножив ноль на любое число, мы получим ноль). Это явная ошибка. В то же время счётчик работает верно, и на самом деле переменная count будет содержать количество неотрицательных чисел (это можно проверить ручной прокруткой). После окончания цикла выводится значение x – последнее введённое число, и значение p, которое всегда будет равно нулю. Таким образом,
Теперь отвечаем на второй вопрос – когда же программа сработает верно, несмотря на ошибки. Второе число всегда будет равно 0, поэтому в последовательности должен быть 0. В то же время последнее введённое число, которое останется в переменной x и будет выведено, должно быть равно количеству неотрицательных чисел. Эти условия выполняются, например для последовательности -5 0 1 3.
Ошибки мы уже фактически нашли ранее: во-первых, для накопления произведения переменную p не нужно обнулять, а нужно записывать в неё начальное значение 1. Во-вторых, выводить нужно не x, а count.
а) неверное начальное значение переменной p: Было: p:= 0; Исправление: p:= 1; б) неверный оператор вывода: Было: writeln(x); Исправление: writeln(count);
В цикле обнаруживаем оператор ввода read(x); который говорит о том, что в переменной x хранится последнее введённое число (а не счётчик неотрицательных чисел!). Это число обрабатывается условными операторами if x < 0 then s := x; if x > mx then mx := x; Из этих строк следует, что в переменную s записывается последнее отрицательное число, а переменная mx – это максимальное из всех элементов последовательности. Сначала обе переменные обнуляются. Таким образом,
Программа неверно подсчитала сумму отрицательных чисел, вместо неё выведено последнее отрицательное число. Поэтому первое значение будет правильным, если это отрицательное число всего одно. Обратим внимание, что начальное значение переменной mx равно 0, поэтому если все числа меньше нуля, максимум будет вычислен неверно. Для правильной программы это начальное значение должно быть не больше, чем минимальное допустимое число, то есть -1000. Таким образом, программа сработает верно, если в последовательности только одно отрицательное число. Это условия выполняются, например для последовательности -5 0 1 3.
Одну ошибку мы уже нашли ранее: начальное значение для переменной mx должно быть не более -1000. Вторая ошибка – сумма отрицательных чисел не накапливается.
а) неверное начальное значение переменной mx: Было: mx:= 0; Исправление: mx:= -1000; б) неверный оператор накопления суммы: Было: s:=x; Исправление: s:=s+x;
Сначала в переменную maxDigit записывается начальное значение N mod 10, это последняя цифра в десятичной записи числа, она равна 4. Заметим, что проверки на делимость этой цифры на 3 не было! Затем в цикле перебираются все цифры числа в обратном порядке (4, 3 и 1), если очередная цифра делится на 3 и больше, чем существующее значение maxDigit, значение maxDigit обновляется – мы нашли новый максимум. в данном случае цифр больше, чем 4, в числе нет, поэтому после окончания цикла maxDigit=4, это число и выводится на экран.
Программа будет выводить правильный ответ, если последняя цифра делится на 3 (например, для числа 136). Есть и другой вариант – когда последняя цифра меньше, чем наибольшая цифра, которая делится на 3 (например, для числа 631).
Для того, чтобы исправить программу, нужно изменить начальное значение maxDigit. Проще всего взять значение, заведомо меньшее, чем любая цифра, например, -1. Поскольку ноль делится на любое число, проверка условия maxDigit=0 не поможет определить, есть ли в числе цифра, кратная трём. Это условие нужно заменить на maxDigit=-1.
а) Было: maxDigit := N mod 10; Исправление: maxDigit := -1; б) Было: if maxDigit=0 then Исправление: if maxDigit=-1 then
В программе сделано несколько ошибок, и в некоторых случаях они могут скомпенсировать друг друга. Во-первых, цикл заканчивается, когда sa, то есть мы всегда находим k, которое на единицу больше правильного значения. С другой стороны, перед циклом стоит два присваивания: |