How do I use the modulo function with this library? - delphi

I am Using this library for Big Integers in Pascal but I am having trouble using the modulo function. Can anyone help?
My code:
a = b modulo(c);
here is the library location: http://www.delphiforfun.org/programs/library/big_integers.htm
{ ***************** Modulo ************* }
procedure TInteger.Modulo(const I2: TInteger);
{ Modulo (remainder after division) - by TInteger }
var
k: int64;
imod3: TInteger;
begin
if high(I2.fDigits) = 0 then begin
divmodsmall(I2.Sign * I2.fDigits[0], k);
assignsmall(k);
end
else
begin
imod3:= GetNextScratchPad;
DivideRem(I2, imod3);
Assign(imod3);
ReleaseScratchPad(imod3);
end;
end;
Why does this not work?:
also why doesnt this work?:
var
P, Q, N, E, D,i: TInteger;
Eing, Cout: TInteger;
begin
E := 3;
D := 27;
N := 55;
writeln(N.Modulo(E));

The source code that you downloaded comes with an example of how to use the modulo function. I urge you to take time to read the example code that comes with a library. If you would do so then you'd be able to solve far more problems by yourself. The example code looks like this:
procedure Tbigints.ModBtnClick(Sender: TObject);
var
i1,i2,i3:Tinteger;
begin
i1:=TInteger.create(0);
i2:=TInteger.create(0);
Getxy(i1,i2);
i1.modulo(i2);
memo1.text:=i1.converttoDecimalString(true);
i1.free;
i2.free;
alloclbl.caption:=format('Allocated memory: %d',[allocmemsize]);
end;
The key point is that the modulo method acts in place. In the code above, the dividend is held in i1 and the divisor in i2. Then you call modulo on i1 passing i2 as the argument. The result of the operation is then placed in i1. So, this method replaces the dividend with the modulus of the division.

Related

Pascal's Triangle output alignment

So I've come up with the code to the values of the triangle itself. What I'm currently strugling is how to aligne/center the values that are printed. I tried many things but, I could use some help now. If anyone has an idea how this can be done feel free to share! Thank you
Program Tri_pas;
Uses Crt;
Var
linha,ordem,a,b: byte;
Function fat(X: byte): real; // factorial
Var fat1: real;
Begin
fat1:=1;
If X <= 1 Then
fat:=1
Else
Begin
Repeat
fat1:=(fat1 * X);
X:=(X - 1);
Until X <= 1;
fat:=fat1;
End;
End;
Procedure nCp(n,p: byte); //Combinations
Var
i: byte;
nCp: real;
Begin
If n < 1 Then
n:=0
Else
n:=(n-1);
For i:=0 to n do
Begin
writeln;
For p:=0 to i do
Begin
nCp:= fat(i) / (fat(p) * fat(i - p)); // mathematic formula for the combinations
Write(nCp:1:0,' ');
End;
End;
End;
{ Main Programa }
Begin
Write('Insert a line(1 -> n) : ');
Readln(linha);
nCp(linha,ordem);
readln;
End.
Just add appropriate number of empty spaces before strings. Note that I used double-spaces, and changed placeholder size to 4 (3+1) to make better formatting.
For p := 1 to (n - i) do
Write(' ');
For p:=0 to i do
Begin
nCp:= fat(i) / (fat(p) * fat(i - p)); // mathematic formula for the combinations
Write(nCp:3:0,' ');
End;
P.S. There are more effective ways to calculate Ncr in reasonable range without real numbers.

Error when using Power in Delphi

I have the following function in my program and it is giving me an EInvalidOp (Invalid Floating Point Operation):
function TMyProgram.GetVal(A, B, C, D, E: double): double;
begin
Result := A/Power((C - D)/(D - B), 1/E);
end;
The values of the parameters are:
A: 320.068,
B: 84.46,
C: 91.632,
D: 24.15,
E: 11
Excel gives me a result of -316.815, but Delphi is giving me an error when I execute this function.
I did a bit more research. The problem is raising a negative base to a fractional exponent. In your particular case you can use mathematical identity to get around it by doing the following:
function TMyProgram.GetVal(A, B, C, D: Double; E: Integer): double;
begin
if Odd(E) and ((C - D)/(D - B) < 0) then
Result := A/-Power(Abs((C - D)/(D - B)), 1/E)
else
Result := A/Power((C - D)/(D - B), 1/E);
end;
This only works when E is an odd number.
-316.81520613
Thats what i get with the power2 function by Jack Lyle.
look here for full code power2
{** A power function from Jack Lyle. Said to be more powerful than the
Pow function that comes with Delphi. }
function Power2(Base, Exponent : Double) : Double;
{ raises the base to the exponent }
CONST
cTiny = 1e-15;
VAR
Power : Double; { Value before sign correction }
BEGIN
Power := 0;
{ Deal with the near zero special cases }
IF (Abs(Base) < cTiny) THEN BEGIN
Base := 0.0;
END; { IF }
... // see the link to full code
END; { FUNCTION Pow }

Alternative to nested for-loop in Delphi

I came across the following (conceptually very simple) problem, and want to write code to do it, but am struggling. Let's say we have two rows of equal length, k. Each cell of each row can be either a 0 or a 1.
For e.g., consider the following row-pair, with k = 5: 01011, 00110
Now if the two rows could freely exchange values at each cell, there would be 2^5 possible combinations of row-pairs (some of which may not be unique). For instance, we could have 00010, 01111 as one possible row-pair from the above data. I want to write code in Delphi to list all the possible row-pairs. This is easy enough to do with a set of nested for-loops. However, if the value of k is known only at run-time, I'm not sure how I can use this approach for I don't know how many index variables I would need. I can't see how case statements will help either because I don't know the value of k.
I am hoping that there is an alternative to a nested for-loop, but any thoughts would be appreciated. Thanks.
Given two vectors A and B of length k, we can generate a new pair of vectors A1 and B1 by selectively choosing elements from A or B. Let our decision to choose from A or B be dictated by a bit vector S, also of length k. For i in [0..k), when Si is 0, store Ai in A1i and Bi in B1i. If Si is 1, then vice versa.
We can define that in Delphi with a function like this:
procedure GeneratePair(const A, B: string; S: Cardinal; out A1, B1: string);
var
k: Cardinal;
i: Cardinal;
begin
Assert(Length(A) = Length(B));
k := Length(A);
Assert(k <= 32);
SetLength(A1, k);
SetLength(B1, k);
for i := 1 to k do
if (S and (1 shl Pred(i))) = 0 then begin
A1[i] := A[i];
B1[i] := B[i];
end else begin
A1[i] := B[i];
B1[i] := A[i];
end;
end;
If we count in binary from 0 to 2k−1, that will give us a sequence of bit vectors representing all the possible combinations of exchanging or not-exchanging characters between A and B.
We can write a loop and use the above function to generate all 2k combinations:
A := '01011';
B := '00110';
for S := 0 to Pred(Round(IntPower(2, Length(A)))) do begin
GeneratePair(A, B, S, A1, B1);
writeln(A1, ', ', B1);
end;
That effectively uses one set of nested loops. The outer loop is the one from 0 to 31. The inner loop is the one inside the function from 1 to k. As you can see, we don't need to know the value of k in advance.
Now that, thanks to Rob, I understand the problem, I offer this recursive solution:
{$APPTYPE CONSOLE}
procedure Swap(var A, B: Char);
var
temp: Char;
begin
temp := A;
A := B;
B := temp;
end;
procedure Generate(const A, B: string; Index: Integer);
var
A1, B1: string;
begin
Assert(Length(A)=Length(B));
inc(Index);
if Index>Length(A) then // termination
Writeln(A, ', ', B)
else
begin // recurse
// no swap
Generate(A, B, Index);
//swap
A1 := A;
B1 := B;
Swap(A1[Index], B1[Index]);
Generate(A1, B1, Index);
end;
end;
begin
Generate('01011', '00110', 0);
Readln;
end.

Delphi XE2 Rounding with DecimalRounding_JH1

Because of a documented rounding issue in Delphi XE2, we are using a special rounding unit available on the Embarcadero site named DecimalRounding_JH1 to achieve true bankers rounding. A link to the unit can be found here:
DecimalRounding_JH1
Using this unit's DecimalRound function with numbers containing a large number of decimal place we
This is the rounding routine from the DecimalRounding_JH1 unit. In our example we call this DecimalRound function with the following parameters (166426800, 12, MaxRelErrDbl, drHalfEven) where maxRelErrDbl = 2.2204460493e-16 * 1.234375 * 2
Function DecimalRound(Value: extended; NDFD: integer; MaxRelErr: double;
Ctrl: tDecimalRoundingCtrl = drHalfEven): extended;
{ The DecimalRounding function is for doing the best possible job of rounding
floating binary point numbers to the specified (NDFD) number of decimal
fraction digits. MaxRelErr is the maximum relative error that will allowed
when determining when to apply the rounding rule. }
var i64, j64: Int64; k: integer; m, ScaledVal, ScaledErr: extended;
begin
If IsNaN(Value) or (Ctrl = drNone)
then begin Result := Value; EXIT end;
Assert(MaxRelErr > 0,
'MaxRelErr param in call to DecimalRound() must be greater than zero.');
{ Compute 10^NDFD and scale the Value and MaxError: }
m := 1; For k := 1 to abs(NDFD) do m := m*10;
If NDFD >= 0
then begin
ScaledVal := Value * m;
ScaledErr := abs(MaxRelErr*Value) * m;
end
else begin
ScaledVal := Value / m;
ScaledErr := abs(MaxRelErr*Value) / m;
end;
{ Do the diferent basic types separately: }
Case Ctrl of
drHalfEven: begin
**i64 := round((ScaledVal - ScaledErr));**
The last line is where we get a floating point error.
Any thoughts on why this error is occurring?
If you get an exception, that means you cannot represent your value as an double within specified error range.
In other words, the maxRelErrDbl is too small.
Try with maxRelErrDbl = 0,0000000001 or something to test if I am right.

How to keep 2 decimal places in Delphi?

I have selected columns from a database table and want this data with two decimal places only. I have:
SQL.Strings = ('select '#9'my_index '#9'his_index,'...
What is that #9?
How can I deal with the data I selected to make it only keep two decimal places?
I am very new to Delphi.
#9 is the character with code 9, TAB.
If you want to convert a floating point value to a string with 2 decimal places you use one of the formatting functions, e.g. Format():
var
d: Double;
s: string;
...
d := Sqrt(2.0);
s := Format('%.2f', [d]);
function Round2(aValue:double):double;
begin
Round2:=Round(aValue*100)/100;
end;
#9 is the tab character.
If f is a floating-point variable, you can do FormatFloat('#.##', f) to obtain a string representation of f with no more than 2 decimals.
For N Places behind the seperator use
function round_n(f:double; n:nativeint):double;
var i,m : nativeint;
begin
m := 10;
for i := 1 to pred(n) do
m := m * 10;
f := f * m;
f := round(f);
result := f / m;
end;
For Float to Float (with 2 decimal places, say) rounding check this from documentation. Gives sufficient examples too. It uses banker's rounding.
x := RoundTo(1.235, -2); //gives 1.24
Note that there is a difference between simply truncating to two decimal places (like in Format()), rounding to integer, and rounding to float.
Nowadays the SysUtils unit contains the solution:
System.SysUtils.FloatToStrF( singleValue, 7, ffFixed, 2 );
System.SysUtils.FloatToStrF( doubleValue, 15, ffFixed, 2 );
You can pass +1 TFormatSettings parameter if the requiered decimal/thousand separator differ from the current system locale settings.
The internal float format routines only work with simple numbers > 1
You need to do something more complicated for a general purpose decimal place limiter that works correctly on both fixed point and values < 1 with scientific notation.
I use this routine
function TForm1.Flt2str(Avalue:double; ADigits:integer):string;
var v:double; p:integer; e:string;
begin
if abs(Avalue)<1 then
begin
result:=floatTostr(Avalue);
p:=pos('E',result);
if p>0 then
begin
e:=copy(result,p,length(result));
setlength(result,p-1);
v:=RoundTo(StrToFloat(result),-Adigits);
result:=FloatToStr(v)+e;
end else
result:=FloatToStr(RoundTo(Avalue,-Adigits));
end
else
result:=FloatToStr(RoundTo(Avalue,-Adigits));
end;
So, with digits=2, 1.2349 rounds to 1.23 and 1.2349E-17 rounds to 1.23E-17
This worked for me :
Function RoundingUserDefineDecaimalPart(FloatNum: Double; NoOfDecPart: integer): Double;
Var
ls_FloatNumber: String;
Begin
ls_FloatNumber := FloatToStr(FloatNum);
IF Pos('.', ls_FloatNumber) > 0 Then
Result := StrToFloat
(copy(ls_FloatNumber, 1, Pos('.', ls_FloatNumber) - 1) + '.' + copy
(ls_FloatNumber, Pos('.', ls_FloatNumber) + 1, NoOfDecPart))
Else
Result := FloatNum;
End;
Function RealFormat(FloatNum: Double): string;
Var
ls_FloatNumber: String;
Begin
ls_FloatNumber:=StringReplace(FloatToStr(FloatNum),',','.',[rfReplaceAll]);
IF Pos('.', ls_FloatNumber) > 0 Then
Result :=
(copy(ls_FloatNumber, 1, Pos('.', ls_FloatNumber) - 1) + '.' + copy
(ls_FloatNumber, Pos('.', ls_FloatNumber) + 1, 2))
Else
Result := FloatToStr(FloatNum);
End;

Resources