Эффективно вычисляя все пифагорейские тройки, зная гипотенузу - PullRequest
7 голосов
/ 28 января 2010

С учетом гипотенузы (c в типичном уравнении a*a + b*b = c*c), каков эффективный способ вычисления всех возможных целочисленных значений a и b, таких, что a < b?

Примечание: я видел, что c больше 1e12, поэтому c*c больше long.MaxValue, насколько я могу судить, c*c вписывается в decimal.

Ответы [ 5 ]

7 голосов
/ 28 января 2010

Все трифы Пифагора (a, b, c) удовлетворяют свойству, что для некоторых целых чисел k, m и n

a = k (m ^ 2-n ^ 2), b = 2kmn, c = k (m ^ 2 + n ^ 2)

Итак, начните с факторинга c. Затем для каждого отдельного фактора k из c (то есть для каждого отдельного подмножества факторов, умноженных вместе), найдите все m и n, которые удовлетворяют c / k = (m ^ 2 + n ^ 2). Выполнение последнего займет значительно меньше времени, чем метод грубой силы, предложенный другими (вам нужно только найти квадраты, которые суммируют с / к, а не с ^ 2), но идентифицируют все тройки (а, б, в) , Вам также не нужно использовать bignums, потому что все промежуточные результаты вписываются в long.

Я также предлагаю вам посетить веб-страницу http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Pythag/pythag.html под заголовком «Более общий пифагорейский тройной калькулятор», который содержит встроенный калькулятор, написанный на javascript, который выполняет именно то, что вы хотите.

6 голосов
/ 28 января 2010

Существует математическое решение, которое быстро находит a и b даже при больших значениях c. К сожалению, не все так просто. Я пытаюсь дать краткое объяснение алгоритма. Надеюсь, это не слишком запутанно.

Так как дано c, и вы ищете a и b, вы в основном хотите решить диофантов уравнения вида

n=x^2+y^2,

где n задано. Не сильно помогает то, что n = c * c - квадрат, и поэтому я описываю решение для любого n. Если бы n было простым числом, то вы могли бы использовать Теорема Ферма , чтобы решить, разрешимо ли ваше уравнение, и использовать, как указал Морон, алгоритм Эрмита-Серре, чтобы найти решения, если таковые имеются.

Чтобы решить случай, когда n не простое, полезно использовать Гауссовы целые числа . (Гауссовы целые числа - это просто комплексные числа с целыми коэффициентами). В частности, отмечается, что норма для x + yi равна

N(x+yi) = x^2+y^2.

Следовательно, нужно найти гауссовы целые числа x + yi, норма которых равна n. Поскольку норма является мультипликативной, достаточно решить это уравнение для факторов n, а затем умножить гауссовы целые числа индивидуальных уравнений. Позвольте мне привести пример. Мы хотим решить

65 = x^2 + y^2.

Это эквивалентно нахождению x, y такого, что

N(x+yi) = 65

над гауссовыми целыми числами. Фактор 65 = 5 * 13, затем мы используем Ферма, чтобы отметить, что оба 5 и 13 могут быть представлены как сумма двух квадратов. Наконец, мы находим либо с помощью грубой силы с помощью алгоритма Эрмита-Серре

N(2+i) = N(1+2i) = ... = 5
N(2+3i) = N(3+2i) = ... = 13

Обратите внимание, я не учел целые числа Гаусса 2-i, -2 + i и т. Д. С отрицательными коэффициентами. Это, конечно, тоже решения.

Следовательно, теперь мы можем умножить эти решения вместе, чтобы получить

65 = 5 * 13 = N (2 + i) * N (2 + 3i) = N ((2 + i) * (2 + 3i)) = N (1 + 8i)

и

65 = 5 * 13 = N (2 + i) * N (3 + 2i) = N ((2 + i) * (3 + 2i)) = N (4 + 7i).

Следовательно, каждый получает два решения

1*1 + 8*8 = 65
4*4 + 7*7 = 65

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


Чтобы вычислить все решения, можно также добавить, что нет необходимости когда-либо вычислять c * c. Найти факторы с - это все, что необходимо. Кроме того, поскольку a и b оба меньше, чем c, не произойдет, что произведения целых гауссовских чисел не будут представлены с 64-битными целочисленными коэффициентами. Следовательно, если соблюдать осторожность, 64-разрядного целого числа достаточно, чтобы решить проблему. Конечно, всегда проще использовать такой язык, как Python, который не имеет таких проблем переполнения.

0 голосов
/ 28 января 2010

Начните со значения 1 для a и значения c для b.

Сравните c*c - b*b с a*a. Если они равны, у вас есть совпадение.

Изменяйте a и b по отношению друг к другу в зависимости от того, какая сторона больше, пока они не станут одинаковыми.

0 голосов
/ 28 января 2010

Учитывая c:

Поскольку b> a, если a является минимальным (a = 1), b = sqrt (c * c - 1).

Следовательно, b ДОЛЖЕН быть между этим значением и c -1.

Кроме того, поскольку b должно быть целым числом, вам необходимо найти первое значение, для которого это целое число.

Now, a property of squares:
The squares are: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, ...
The differences: -, 3, 5, 07, 09, 11, 13, 15, 17, 019, 021, ...
That means a square can be written as a summation of ODD numbers:
    1 + 3 + 5 + 7 + n+...
where n = number the summation is a square of.

Таким образом, ровно c квадратных чисел меньше, чем c * c, и вы можете идентифицировать их, используя простое вычитание.

Возвращаясь к началу, беря b = sqrt (c c - 1), округляя вниз и беря b b, получаем квадрат b, который должен быть выше, а a a = 1 Найдите c c - (a a + b b). Это должно дать вам число, которое должно быть ДОБАВЛЕНО для достижения c * c.

Поскольку вы можете добавить 3 + 5 + 7 + ... к a и b+2 + b+4 + b+6 + ... к b, вам просто нужно найти правильный термин, основанный на суммах, а не на самом квадрате:)

0 голосов
/ 28 января 2010

Можно пойти и на библиотеку BigNum.

Что касается эффективного способа нахождения a и b:

Для каждого значения b (начиная с c-1 и опускаясь до b * b

...