1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| type
UIntBig = record
private
type TInternalItem = UInt64;
type TInternalData = array of TInternalItem;
var Data: TInternalData;
const BitOrder = 63-16;
const BigBit = TInternalItem(1) shl BitOrder - 1; // 7FFF FFFF FFFF en 47 soit 63-16
const ToStringStep = 4;
public
class function Create(AValue: TInternalItem = 0): UIntBig; static;
function Add(Other: UIntBig): UIntBig;
function ToString(): string;
end;
procedure TrianglePascal100(AStrings: TStrings = nil);
procedure ToStrings(const I: array of UIntBig);
var
J: Integer;
S: string;
begin
if Assigned(AStrings) then
begin
S := I[Low(I)].ToString();
for J := Succ(Low(I)) to High(I) do
S := S + ' ' + I[J].ToString();
AStrings.Add(S);
end;
end;
var
Curr, Next: array of UIntBig;
I, J: Integer;
begin
// Ligne 1 c'est 1
AStrings.Add('1');
// Ligne 2 c'est 1 1 - exprimé par le tableau ci dessous
SetLength(Curr, 2);
Curr[0] := UIntBig.Create(1);
Curr[1] := UIntBig.Create(1);
ToStrings(Curr);
// Ligne 3 c'est 1 2 1 - c'est lui que l'on cherche à calculer
for I := 3 to 200 do
begin
SetLength(Next, Length(Curr) + 1);
Next[0] := Curr[0];
for J := Succ(Low(Curr)) to High(Curr) do
Next[J] := Curr[J - 1].Add(Curr[J]);
Next[High(Next)] := Curr[High(Curr)];
Curr := Next;
ToStrings(Curr);
end;
// 100ème donc avec un indice en base 0 c'est le 99, reflexe habituel avec un tableau
AStrings.Add('100ème');
AStrings.Add(Curr[99].ToString());
end;
{ UIntBig }
//------------------------------------------------------------------------------
function UIntBig.Add(Other: UIntBig): UIntBig;
var
I, L: Integer;
Sum, Carry: TInternalItem;
begin
if (Length(Self.Data) > 0) and (Length(Other.Data) > 0) then
begin
L := Max(Length(Self.Data), Length(Other.Data));
SetLength(Result.Data, L);
Carry := 0;
for I := 0 to L - 1 do
begin
Sum := Carry;
if I <= High(Self.Data) then
Sum := Sum + Self.Data[I];
if I <= High(Other.Data) then
Sum := Sum + Other.Data[I];
(*
if Sum > BigBit then
Beep();
*)
Result.Data[I] := Sum and BigBit;
Carry := Sum shr BitOrder;
end;
if Carry > 0 then
begin
SetLength(Result.Data, L + 1);
Result.Data[L] := Carry;
end;
end
else if Length(Self.Data) > 0 then
Result := Self
else
Result := Other;
end;
//------------------------------------------------------------------------------
class function UIntBig.Create(AValue: TInternalItem = 0): UIntBig;
var
L: Integer;
Carry: TInternalItem;
begin
Carry := 0;
L := 1;
SetLength(Result.Data, L);
if AValue > 0 then
begin
Result.Data[0] := AValue and BigBit;
Carry := AValue shr BitOrder;
if Carry > 0 then
begin
SetLength(Result.Data, L + 1);
Result.Data[L] := Carry;
end;
end
else
Result.Data[0] := 0;
end;
//------------------------------------------------------------------------------
function UIntBig.ToString(): string;
var
I: Integer;
Temp: TInternalData;
Sum, Carry, Step: TInternalItem;
begin
if Length(Self.Data) > 0 then
begin
Temp := Copy(Self.Data);
Result := '';
Step := Trunc(IntPower(10, ToStringStep));
while (Length(Temp) > 0) and (Temp[0] > 0) do
begin
Carry := 0;
for I := High(Temp) downto Low(Temp) do
begin
Sum := Carry shl BitOrder;
Sum := Sum or Temp[I];
DivMod(Sum, Step, Temp[I], Carry);
//Temp[I] := Sum div Step;
//Carry := Sum mod Step;
end;
if Temp[High(Temp)] = 0 then
SetLength(Temp, High(Temp));
if Length(Temp) > 0 then
Result := Format('%.*d', [ToStringStep, Carry]) + Result
else
Result := Format('%d', [Carry]) + Result;
end;
end
else
Result := '0';
end; |
Partager