Я прочитал a problem about bullseyes в Google Code Jam. (Конкурс завершен сейчас, так что это нормально, чтобы говорить об этом)Как точно решить квадратичные уравнения с большими целыми коэффициентами (по целым числам)?
Марии начинается с т миллилитров черной краски, которую она будет использовать, чтобы рисовать кольца толщиной 1 см (один сантиметр). Кольцо толщиной 1 см представляет собой пространство между двумя концентрическими кругами, радиусы которых отличаются на 1 см.
Мария рисует первое черное кольцо вокруг белого круга радиуса r см.
Площадь диска с радиусом 1 см составляет π см2. Для покрытия площади π см2 требуется один миллилитр краски. Каково максимальное количество черных колец, которые Мария может нарисовать?
По моим подсчетам на бумаге, площадь краски, чтобы нарисовать яблочко с п кольцом, внутренним радиусом, а кратно пи является 2*n**2 + n*(2*r-1)
Поэтому, учитывая t*pi
millitres краски проблемы найти наибольшее n такое, что f(n,r) <= t
.
Этим утром я решил, что с двоичным поиском https://github.com/hickford/codejam/blob/master/2013/1A/bullseye/bullseye.py
Я выбрал бинарный поиск по квадратному уравнению, потому что я очень настороженно относится к точке неточностей плавающей - в этой задаче т и р являются целыми числами, как большие, как 10 ** 18). Арифметическая неточность укусила меня в предыдущем коду.
Но мне любопытно. Можете ли вы укрепить квадратичное уравнение, чтобы дать правильный ответ для уравнений с большими целыми коэффициентами? Могут ли библиотеки математики, такие как Sympy или Numpy, что-нибудь предложить?
Демонстрация того, что квадратичное уравнение дает неправильный ответ для больших входов. Например, с r=308436464205151562
и t=1850618785230909388
. Квадратичное уравнение для решения -
2*n**2 + 616872928410303123*n -1850618785230909388 <= 0
ie. коэффициенты
a = 2
b = 616872928410303123
c = -1850618785230909388
Вычислительный в Python
> int((-b + math.sqrt(b**2 - 4*a*c))/(2*a))
0
Это неправильный ответ! Правильный ответ (найденный бинарный поиск) является 3
>>> n = 3
>>> 2*n**2 + 616872928410303123*n -1850618785230909388 <= 0
True
Разве вы не просто используете квадратичное уравнение? –
В предыдущей ошибке кода я был укушен ошибкой точности с плавающей точкой http://stackoverflow.com/q/15978781/284795 –
У вас не должно возникнуть проблемы с использованием math.sqrt для целого числа, которое мало. –