Символ Якоби

Символ Якоби, J(a,n), представляет собой обобщение символа Лежандра на составные модули, он определяется для любого целого a и любого нечетного целого n. Функция удобна при проверке на простоту. Символ Якоби является функцией на множестве полученных вычетов делителей n и может быть вычислен по различным формулам [1412]. Вот один из способов:

Определение 1: J(a,n) определен, только если n нечетно.

Определение 2: J(0,n) = 0.

Определение 3: Если n - простое число, то символ Якоби J(a,n) = 0, если a делится на n.

Определение 4: Если n - простое число, то символ Якоби J(a,n) = 1, если a - квадратичный вычет по модулю n.

Определение 5: Если n - простое число, то символ Якоби J(a,n) = -1, если a не является квадратичным вычетом по модулю n.

Определение 6: Если n - составное число, то символ Якоби J(a,n) = J(a,p1)* ... * J(a,pm), где p1, ... , pm - это разложение n на простые сомножители.

Следующий алгоритм рекурсивно рассчитывает символ Якоби:

Правило 1: J(1,n) = 1

Правило 2: J(a*b,n) = J(a,n)* J(b,n)

Правило 3: J(2,n) =, если (n2-1) /8 нечетно, и -1 в противном случае

Правило 4: J(a,n)= J((a mod n),n)

Правило 5: J(a, b1*b2) = J(a, b1)* J(a, b2)

Правило 6: Если наибольший общий делитель a и b = 1, а также a и b нечетны:

Правило 6a: J(a,b)= J(b, a), если (a - l)(b - 1)/4 четно

Правило 6b: J(a,b)= -J(b, a), если (a - l)(b - 1)/4 нечетно

Вот алгоритм на языке C:

/* Этот алгоритм рекурсивно вычисляет символ Якоби */

int jacobi(int a, int b) {

int g;

assert(odd(b));

if (a >= b) a %= b; /* по правилу 4 */

if (a == 0) return 0; /* по определению 1 */

if (a == 1) return 1; /* по правилу 1 */

if (a < 0)

if ((b-l)/2 % 2 == 0)

return jacobi(-a,b);

else

return -jacobi(-a,b);

if (a % 2 == 0) /* a четно */

if (((b*b -1)/8) % 2 == 0)

return +jacobi(a/2,b);

else

return -jacobi(a/2,b); /* по правилам 3 и 2 */

g = gcd(a,b);

assert(odd(a)); /* это обеспечивается проверкой (a % 2 == 0) */

if (g == a) /* b делится на a */

return 0; /* по правилу 5 */

else if (g != 1)

return jacobi(g,b)*jacobi(a/g,b); /* по правилу 2 */

else if (((a-l)*(b-l)/4) % 2 == 0)

return +jacobi(b,a); /* по правилу 6a */

else

return -jacobi(b,a); /* по правилу 6b */

}

Если заранее известно, что n - простое число, вместо использования предыдущего алгоритма просто вычислите a((n-1)/2) mod n, в этом случае J(a,n) эквивалентен символу Лежандра.

Символ Якоби нельзя использовать для определения того, является ли a квадратичным вычетом по модулю n (если, конечно, n не является простым числом). Обратите внимание, что если J(a,n) = 1 и n - составное число, то утверждение, что a является квадратичным вычетом по модулю n, не обязательно будет истиной. Например:

J(7,143) = J(7,11)* J(7,13) = (-1)(-1) = 1

Однако не существует таких целых чисел x, что x2 ? 7 (mod 143).