Вы по сути пытаетесь решить проблему
2 i x = w
и затем находите наименьшее целое число больше i.Решая, мы получаем
2 i = w / x
i = log 2 (w / x)
Таким образом, один из подходов состоит в том, чтобы явно вычислить это значение, а затем взять потолок.Конечно, вам придется остерегаться численной нестабильности при этом.Например, если вы используете float
s для кодирования значений, а затем разрешите w = 8 000 001 и x = 1 000 000, вы получите неправильный ответ (3 вместо 4).Если вы используете double
s для хранения значения, вы также получите неправильный ответ, когда x = 1 и w = 536870912 (отчет 30 вместо 29, так как 1 x 2 29 = 536870912, но из-зана неточности в двойном ответе ошибочно округлено до 30).Похоже, нам придется переключиться на другой подход.
Давайте вернемся к вашему первоначальному решению, просто удвоив значение x до тех пор, пока оно не превысит w, здесь должно быть совершенно нормально.Максимальное количество раз, которое вы можете удвоить x, пока оно не достигнет w, задается в log 2 (w / x), и, поскольку w / x составляет не более одного миллиарда, это повторяет самое большее log 2 10 9 раз, что примерно в тридцать раз больше каждого.Выполнение тридцати итераций умножения на два, вероятно, будет чрезвычайно быстрым.В более общем случае, если верхняя граница w / x равна U, то для ее завершения потребуется не более O (log U) времени.Если у вас есть k (x, w) пар для проверки, это займет время O (k log U).
Если вы не удовлетворены этим, есть еще один очень быстрый алгоритм, который вы можете попробовать.По сути, вы хотите вычислить лог 2 ш / х.Вы можете начать с создания таблицы, в которой перечислены все степени двух, а также их логарифмы.Например, ваша таблица может выглядеть следующим образом:
T[1] = 0
T[2] = 1
T[4] = 2
T[8] = 3
...
Затем вы можете вычислить w / x, а затем выполнить двоичный поиск, чтобы выяснить, в каком диапазоне находится значение.Верхняя граница этого диапазона - это количество раз, когда мяч должен отскочить.Это означает, что если у вас есть k разных пар для проверки, и если вы знаете, что максимальное отношение w / x равно U, создание этой таблицы занимает время O (log U), а затем каждый запрос занимает время, пропорциональное журналу размератаблицы, которая является O (log log U).Тогда общее время выполнения O (log U + k log log U), что очень хорошо.Учитывая, что вы имеете дело не более чем с одним миллионом проблемных случаев и что U составляет один миллиард, k log log U составляет чуть менее пяти миллионов, а log U - около тридцати.
Наконец, если вы готовычтобы делать извращенно ужасные вещи с побитовым хакерством, поскольку вы точно знаете, что w / x вписывается в 32-битное слово, вы можете использовать этот побитовый трюк с IEEE, удваивающим довычислить логарифм в очень небольшом количестве машинных операций.Это, вероятно, будет быстрее, чем два вышеупомянутых подхода, хотя я не могу обязательно гарантировать это.
Надеюсь, это поможет!