Учитывая неотрицательное целое число c
, мне нужен эффективный алгоритм для нахождения наибольшего целого числа x
такого, что
x*(x-1)/2 <= c
Соответственно, мне нужен эффективный и надежно точный алгоритм для вычисления:
x = floor((1 + sqrt(1 + 8*c))/2) (1)
Для определенности я пометил этот вопрос как C++, поэтому ответом должна быть функция, написанная на этом языке. Вы можете предположить, что c
является 32-битным целым числом без знака.
Кроме того, если вы можете доказать, что (1) (или эквивалентное выражение, включающее арифметику с плавающей запятой) всегда дает правильный результат, это тоже правильный ответ, поскольку вычисления с плавающей запятой на современных процессорах могут быть быстрее, чем целочисленные алгоритмы.
c
? - person phs   schedule 02.10.2014c
- это 32-битное целое число без знака. - person becko   schedule 02.10.2014O(1)
(полагаю, я еще не прогонял ваши коэффициенты по формуле quad.) Вы ищете хитрости? - person phs   schedule 02.10.2014O(1)
закрытой формой вы подразумеваете выражениеfloor((1 + sqrt(1 + 8*c))/2)
, обратите внимание, что оно включает арифметику с плавающей запятой, которая может быть неточной. Я не проверял, всегда ли в этом случае он дает правильный результат. - person becko   schedule 02.10.2014x
, т.е. реши его математически. Затем подумайте, как написать соответствующий код. Во всяком случае, что вы пробовали сами до сих пор? - person Ulrich Eckhardt   schedule 02.10.2014x = floor((1 + sqrt(1 + 8*c))/2)
(я написал его в вопросе), и я знаю, как это запрограммировать на C++. Проблема в том, что это включает арифметику с плавающей запятой, и я не уверен, всегда ли это будет точно для всех возможных значенийc
- person becko   schedule 02.10.2014x = floor((1 + sqrt(1 + 8*c))/2)
. Кажется, он дает точные результаты для значенийc
, которые я пробовал. Но я хотел бы увидеть доказательство/гарантию того, что эта формула (или ее эквивалентная версия) всегда дает точные результаты. Я также могу придумать метод разделения пополам для поискаx
, но я не стал его программировать, так как подозреваю, что есть решения получше. - person becko   schedule 02.10.2014c
? У вас есть ссылка, где я могу найти доказательство? - person becko   schedule 02.10.2014x(x-1)/2
— это просто сумма первыхx-1
натуральных чисел. Вы можете создать таблицу поиска со всеми записями, еслиc
никогда не бывает слишком большим, но еслиc
может занимать весь 32-битный диапазон, вам может быть лучше с приличной реализацией целочисленного квадратного корня или просто иметь дело с плавающей запятой (что уже не так медленно, как раньше). - person twalberg   schedule 02.10.2014sqrt
. - person AndyG   schedule 02.10.2014sqrt
, этого будет более чем достаточно для 32-битных целых чисел. См. stackoverflow.com/a/4319151/5987. - person Mark Ransom   schedule 02.10.2014