Расшифровка назначения функции в C с двумя для вложенных циклов, одним вводом int и возвратом int

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

Я пробовал визуализировать данные, но не смог сделать никаких значимых выводов из графика: Расшифровка назначения функции в C с двумя для вложенных циклов, одним вводом int и возвратом int (синий - это возвращаемое значение mistery, оранжевый - разница между последним и текущим возвращением. Для удобства чтения шкала логарифмическая.)

int mistery(int n){
    int i, j, res=0;
    for(i = n / 2; i <= n; i++){
        for(j = 2; j <= n; j *= 2){
          res += n / 2;
        }
    }
    return res;
}

Это похоже на случайный код, но я действительно видел лист, где это появляется. Любой вклад приветствуется.

Спасибо

Вы уверены, что это правильный код? Внешний цикл не взаимодействует ни с чем внутри, поэтому его можно заменить умножением. Кроме того, n / 2 является константой в res += n/2, и ее также можно вынести за одно умножение. Эти 2 факта предполагают, что где-то есть ошибка.

SergGr 07.01.2019 18:25

в нынешнем виде этот код просто вычисляет значение n / 2 * floor (log n) * floor (n / 2), логарифм равен основанию 2.

Yakov Dan 07.01.2019 18:28

@YakovDan, я не думаю, что вы правильно поняли формулу (например, внешний цикл for не является ни n/2, ни floor(n/2)), но да, это достаточно близко и для меня тоже не имеет смысла.

SergGr 07.01.2019 18:29

@SergGr Я перепроверил. Это.

Daniel Silva 07.01.2019 18:30

@SergGr, конечно, правильное значение floor (n / 2) +1.

Yakov Dan 07.01.2019 18:31

В этом случае он просто вычисляет функцию. ничего особенного в этом нет.

Yakov Dan 07.01.2019 18:31

Это действительно имеет смысл, поскольку петли не взаимодействуют друг с другом!

Daniel Silva 07.01.2019 18:33

Верно. это в основном n / 2 плюс n / 2 плюс n / 2 ...., повторяется k раз. k кажется (floor (n / 2) +1) * floor (log n), но я предлагаю вам дважды проверить это.

Yakov Dan 07.01.2019 18:34

@SergGr, На мой взгляд, в английском предложении n/2 интерпретируется в математическом смысле, а не как оператор языка программирования c. В любом случае, когда вы пишете пол (n / 2), вы получаете одно и то же числовое значение в любой интерпретации по вашему выбору - C или математике.

Yakov Dan 07.01.2019 18:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
65
1

Ответы 1

Приращение, добавляемое к переменной результата на каждой итерации внутреннего цикла, зависит только от параметра функции п, который функция не изменяет. Таким образом, результатом является произведение приращения (n/2) на общее количество итераций внутреннего цикла (при условии, что не происходит переполнения).

Итак, сколько существует итераций цикла? Рассмотрим сначала внешний цикл. Если бы нижняя граница i была равна 0, то включающая верхняя граница n дала бы итерации n+1. Но мы пропускаем первые итерации n/2 (0 ... (n/2)-1), так что это n+1-(n/2). Все деления здесь являются делениями целое число, и с целочисленным делением для всех мм> верно, что мм> = (мм> / 2) + ((мм> + 1) / 2). Мы можем использовать это, чтобы переписать количество итераций внешнего цикла как ((n+1)/2) + 1 или (n+3)/2 (все еще используя целочисленное деление).

Теперь рассмотрим внутренний цикл. Переменная индекса j начинается с 2 и удваивается на каждой итерации, пока не превысит значение n. Это дает количество итераций, равное нижнему пределу логарифма по основанию 2 n. Таким образом, общее количество итераций составляет

(n+3)/2 * floor(log2(n))

(предположим, что мы можем предположить точный результат, когда n является степенью двойки). Комбинированный результат, таким образом, будет

((n+3)/2) * (n/2) * floor(log2(n))

где деления по-прежнему являются целочисленными делениями и выполняются до умножения. Это объясняет, почему производная функции резко возрастает при мощности двух аргументов: количество итераций внешнего цикла увеличивается на единицу в каждой из этих точек.

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

  • он растет асимптотически быстрее, чем п2, и асимптотически медленнее, чем п3. По факту,
  • он имеет форму, напоминающую те, которые имеют тенденцию появляться в вычислительных асимптотических границах, поэтому, возможно, это оценка или граница памяти или времени, которые потребуются для некоторых вычислений. Также,
  • он строго увеличивается для п> 0. Это может быть не сразу понятно из-за задействования целочисленного деления, но обратите внимание, что п и п + 3 имеют противоположную четность, поэтому всякий раз, когда п увеличивается на единицу, ровно одно из п / 2 и ( п + 3) / 2 увеличивается на одно, а другое не изменяется (и логарифмический член не убывает).
  • как уже обсуждалось, он имеет внезапные скачки при степени 2. Это можно рассматривать с точки зрения количества итераций внешнего цикла или, альтернативно, с точки зрения участия функции floor() в форме одного уравнения.
  • Полиномиальная часть функции связана с уравнением для суммы целых чисел от 1 до п.
  • Логарифмическая часть функции связана с количеством значащих битов в двоичном представлении п.

Другие вопросы по теме