BTW, für HugeInt_Mod konnte ich außer daß das Ergebnis negativ ist, wenn A negativ ist, bisher keinen Fehler feststellen(Der "Oops-Fehler"). Kann man ein A div X iregndwie als mod casten und zurückrechnen, ansonsten bleibt nur Result[I]:= R div B gesondert zu behandeln (N* Subtraktion).
Das mit dem casten verstehe ich nicht. Man hat bei richtiger Implementation von div und mod die Formel
A = (A div B)*B + A mod B also
A div B = (A - A mod B) div B ohne Rest, aber das könnte die Sache noch verschlimmern, weil dann eventuell ja eine weitere 0 weggeshiftet wird. Ansonsten ist hier
ein Fix ohne Garantie für die Original-Routine. Die Anzahl der R-Stellen wird vorher berechet und damit eine for-Schleife durchlaufen:
Delphi-Quellcode:
procedure HugeInt_DivMod(
var A: HugeInt; B: HugeInt;
var R: HugeInt);
{ R := A div B; A := A mod B }
var
MaxShifts, S, Q, I: integer;
D, E: HugeInt;
A_IsNeg, B_IsNeg: boolean;
begin
A_IsNeg:= HugeInt_IsNeg(A);
B_IsNeg:= HugeInt_IsNeg(B);
if A_IsNeg
then HugeInt_Min(A);
if B_IsNeg
then HugeInt_Min(B);
if HugeInt_Comp(A, B) < 0
then
{ A<B; no need to divide }
FillChar(R, SizeOf(R), 0)
else
begin
FillChar(R, SizeOf(R), 0);
Move(B, D, SizeOf(HugeInt));
{ first work out the number of shifts }
MaxShifts:= HugeInt_HCD(A)- HugeInt_HCD(B);
S:= 0;
while (S <= MaxShifts)
and (HugeInt_Comp(A, D) >= 0)
do
begin
Inc(S);
HugeInt_SHL(D, 1);
end;
{ while }
Dec(S);
for I:=S
downto 0
do begin
{ Make A new copy of B }
Move(B, D, SizeOf(HugeInt));
{ Shift D as needed }
HugeInt_ShL(D, I);
{ Use E = -D for addition, faster then subtracting D }
Move(D, E, SizeOf(HugeInt));
HugeInt_Min(E);
Q:= 0;
{ while A >= D do A := A+-D and keep trek of # in Q}
while HugeInt_Comp(A, D) >= 0
do
begin
HugeInt_Add(A, E, A);
Inc(Q);
end;
{ while }
{ OOps!, one too many subtractions; correct }
if HugeInt_IsNeg(A)
then
begin
HugeInt_Add(A, D, A);
Dec(Q);
end;
{ if }
R[I]:= Q;
end;
if A_IsNeg
Xor B_IsNeg
then HugeInt_Min(R);
end;
{ else }
end;
{ HugeInt_Div }
Für die bisherigen Fälle und zB für (456*123456+78) div 456 scheint's zu laufen, aber ...! Die minimale Änderung hat den undurchsichtigen Code nicht klarer gemacht.