Полная версия этой страницы:
Деление с остатком
Нужно реализовать деление с остатком больших чисел, но не могу разобраться в алгоритме - и читабельного не нашел к сожалению. Везде какие-то неточности, и абсурдные на мой взгляд вещи.
Во-первых, глупейший вопрос: если я для хранения больших чисел использую, к примеру,
Код
type
TDigit = array[0..63] of dword;
то наименьшему или наибольшему элементу массива логичнее хранить младшую часть числа?
Etoprostoya
09 Apr 2010, 10:00
Обычно младшая часть в начальных ячейках, а старшая - в ячейках с бОльшим адресом.
Был бы ты сишник, а не паскалист - "послал" бы тебя по разным источникам. Например,
http://algolist.manual.ru/maths/longnum.php
Цитата
var a,b,c: TDigit;
a
b mod c = ?
для "Монтгомери" нужно сначала произвести деление...
Etoprostoya
13 Apr 2010, 21:26
Можно поконкретнее описать, что нужно? И большая ли степень b? TDigit - целое число? Модуль c имеет какие-то особенности, например c=2N или c=2N+1?
Добавлено ([mergetime]1271183161[/mergetime]):
С Монтгомери плохо знаком.
Так вот я описал что нужно найти. Куда это вставляется сам точно не знаю. TDigit объявлен в первом посте, все три числа произвольные.
Etoprostoya
13 Apr 2010, 21:41
Всё равно не очень понятно.
Вариант: тупо умножать x="a" на "a" b-1 раз, а потом вычислить остаток от деления на "c".
В том-то и дело, что это не вариант

степень - число до 2048 бит, аргумент - тоже. Даже если бы они были по 32 бит, никакой памяти бы не хватило на хранение результата возведения в степень, да и сколько времени это бы длилось...
А вот статьи, в которых не понял смысла некоторых выражений и обозначений (похоже на опечатки, но кто знает):
Деление:
http://naukoved.ru/content/view/1300/45/Монтгомери:
http://dic.academic.ru/dic.nsf/ruwiki/1277680http://naukoved.ru/content/view/1301/45/
Etoprostoya
13 Apr 2010, 21:51
Есть вариант для такого случая: после каждого умножения находить остаток от деления на "c" и потом умножать уже на него.
не, количество итераций умножения / деления все равно будет слишком большим.
Etoprostoya
13 Apr 2010, 22:23
Есть алгоритмы, оптимизирующие количество умножений при возведении в степень.
Например: x^16 - 15 умножений?
A = x*x = x^2; B = A*A = x^4; C = B*B = x^8; D = C*C = x^16. То есть 4 умножения. Для x^31 придётся выполнить, кажется, 7 умножений. В среднем 2*log2b умножений.
После каждого умножения находим остаток и потом используем его.
gamecreator
14 Apr 2010, 07:47
Цитата(FBX @ 13 Apr 2010, 22:48)
насколько я понял, это алгоритм компьютерного деления.
еще вариант:
( a * b ) mod c = ( ( a mod c ) * ( b mod c ) ) mod c
в твоем варианте:
( a ^ b ) mod c = ( ( a mod c ) ^ b ) mod c
Пришлось использовать для хранения чисел string, причем в читабельной десятичной форме. Сел сегодня, что-то сваял, для размера основания, степени и делителя по ~2048 бит программа работала 85 секунд. Если ~512 бит, то 1.5 секунд. Монтгомери ниасилил, поэтому сделал по-тупому.
Всем еще раз спасибо за помощь.
hippocamus
04 May 2010, 15:58
возведение в целую степень. быстрый алгоритм.
Код
function Power (A, B: Int64): Int64; {или LongInt?}
begin
Result := 1;
while (B > 0) do
begin
if (B and 1 = 1) then Result := Result * A;
A := A + A;
B := B shr 1;
end;
end;
Или вот, в общем случае:
Код
function Power (A, B: Double): Double;
begin
if (A < 0) then Result := -1 * Exp(B * Ln(Abs(A)))
else if (A > 0) then Result := Exp(B * Ln(Abs(A)))
else Result := 0;
if (Round(B) mod 2 = 0) then Result :=Abs(Result);
if (B = 0) then Result := 1;
end;
gamecreator
04 May 2010, 15:59
а что такое х?
hippocamus
04 May 2010, 16:01
исправил.
gamecreator
04 May 2010, 16:25
xa=Пi=0∞(x-ki)ai где
aєR
ai=[a'i]
a'0=a
a'i={a'i-1}*k
Добавлено ([mergetime]1272979500[/mergetime]):
Пi=0∞ - имеется ввиду произведение от 0 до бесконечности
gamecreator
04 May 2010, 18:30
дык это способ.
Добавлено ([mergetime]1272987048[/mergetime]):
можно еще в ряд Тейлора раскладывать в окрестности 1
Как реализовать расширенный алгоритм Евклида
(
http://www.cyberguru.ru/cpp-sources/algori...tm-evklida.html )
да так, чтобы Y получился гарантированно отрицательный, а X - положительный.
(точнее, оба они получились положительные в формуле ax - by = НОД)
gamecreator
10 May 2010, 13:49
а никак. поменять a и b местами. и алгоритмы там кривые.
GCD(a,


b==0)?a:GCD(b,a mod

.
bx+(a mod

y=ay+b(x-[a/b]y)
Добавлено ([mergetime]1273488582[/mergetime]):
код на с++
Код
int gcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
int res;
res=gcd(b,a%b,y,x);
y-=(a/b)*x;
return res;
}
В этом коде выходит что x не меняется...
А еще проблема в том, что числа, с которыми приходится работать - большие, и отрицательными быть не могут. Я не знаю как быть...
gamecreator
10 May 2010, 15:07
меняется. это была проверка на внимательность и ты ее не прошел.
Добавлено ([mergetime]1273493270[/mergetime]):
а почему они не могут быть отрицательными?
Потому что можно это реализовать без геморной реализации отрицательных чисел
gamecreator
10 May 2010, 15:42
этот алгоритм - нельзя
Добавлено ([mergetime]1273495326[/mergetime]):
и она не геморная. давай исходники, я ее приделаю
и будет ли целесообразным такой результат?
ведь у уравнения 1 = xr - yn есть больше одного решения, почему-то в примере для одних и тех же чисел там указаны другие числа, которые подходят, но тем не менее, по знаку положительные. Только там не был дан алгоритм, только отсылка на расш.Евклида.
r = 1024 n = 789
x = 742 y = 963
по обычному алгоритму другие числа получаются (-47, -61)
gamecreator
10 May 2010, 19:35
оба верны
Добавлено ([mergetime]1273509342[/mergetime]):
789-742=47
1024-963=61
думаю, происхождение чисел очевидно.
Точно... надеюсь, это верно во всех случаях.
gamecreator
11 May 2010, 15:51
во всех, можешь не сомневаться
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.