I want to create a Fibonacci sequence using a for loop, but the integers are not adding up - delphi

procedure TForm1.Button1Click(Sender: TObject);
var
term1: integer;
term2: integer;
term3: integer;
j: integer;
begin
term1 := (0);
term2 := (1);
for j := 1 to 100 do;
begin
term3 :=( term1 + term2);
Memo1.Text:=inttostr(term3);
term1 := term2;
term2 := term3;
end;
end;
end.
This is what I have so far, but term1 and term2 don't want to add up. I have tried some different things, but for some reason the integers never want to add up.

There are several problems with your code
The semicolon after for j := 1 to 100 do prevents your next code that is withing begin..end block to be run in a loop. Why? The code that is to be run in each cycle of for loop is the one that follows the do until the first semicolon. Since you put semicolon just after the do this basically means that empty block of code is ran in a loop. Your begin..end block comes after that. Removing the semicolon after do will fix that.
You are using Memo1.Text:=inttostr(term3); to write the result into Memo. The problem with this is that this will rewrite entire text of the Memo every time so you will end up with only one line showing the last number. You should use Memo1.Lines.Add(inttostr(term3)); instead so that new line is added each time.
Lastly you are using Integer type for your variables. Since numbers in Fibonacci sequence grows very fast you will quickly exceed the maximum value that can be stored in Integer which in Delphi is Signed 32 bit Integer with a max value of 2147483647. You will have to use bigger integer types like 64 bit Integer type and since you are only dealing with positive numbers you should therefore use Unsigned 64 bit Integer that in declared in Delphi by UInt64 type. You can read more about Delphi default Integer types in documentation. Unfortunately not even UInt64 will is big enough for value of all first 100 numbers of Fibonacci sequence. So you will have to use one of the BigIntegers libraries for Delphi to do this properly. There are several of them available on internet.

You have an erroneous ; on your loop that you need to remove:
for j := 1 to 100 do;
^

Related

Low bound exceeds high bound & Duplicate case label if you swap'em cntCaseTbl(Z : Int64): Int64; Error in Case Table

I'm getting this error on the code below:
Low bound exceeds high bound
If you swap them, you get a different error:
Duplicate case label
What can I do?
I've tried all of them without Int64() and with Int64(), but it didn't help.
Try for yourself, errors exist no matter if you type cast or not.
There's several ways to do this below, but I want to know why this code errors the way it does:
Delphi can not use below because it can not achieve 64-bit processing on case statements.
function cntCaseTbl(Z: Int64): Int64;
begin
case Abs(Z) of
0..9: Exit(1);
10..99: Exit(2);
100..999: Exit(3);
1000..9999: Exit(4);
10000..99999: Exit(5);
100000..999999: Exit(6);
1000000..9999999: Exit(7);
10000000..99999999: Exit(8);
100000000..999999999: Exit(9);
1000000000..9999999999: Exit(10);
10000000000..99999999999: Exit(11);
100000000000..999999999999: Exit(12);
1000000000000..9999999999999: Exit(13);
10000000000000..99999999999999: Exit(14);
100000000000000..999999999999999: Exit(15);
1000000000000000..9999999999999999: Exit(16);
10000000000000000..99999999999999999: Exit(17);
100000000000000000..999999999999999999: Exit(18);
1000000000000000000..9223372036854775807: Exit(19);
end;
end;
On line 131, 10000000000 and 99999999999 are Integers that are being type-casted to Int64, and they are both outside of the range of Integer, so they are overflowing before being casted, thus causing the 1st value to be less than the 2nd value, hence the error.
Same with the other lines, too.
This is described in Delphi's documentation:
Case Statements
The case statement may provide a readable alternative to deeply nested if conditionals. A case statement has the form:
case selectorExpression of
caseList1: statement1;
...
caseListn: statementn;
end
where selectorExpression is any expression of an ordinal type smaller than 32 bits (string types and ordinals larger than 32 bits are invalid) ...
I would suggest getting rid of the case altogether and just use a loop instead, eg:
function cntCaseTbl(Z: Int64): Int64;
begin
Result := 0;
Z := Abs(Z);
while Z > 0 do begin
Inc(Result);
Z := Z div 10;
end;
end;

Incorrect behaviour of a for loop

I have encountered some incorrect behaviour in a procedure to write a UT8String to a stream (Delphi 10.3). The procedure is very straightforward and reads:
procedure StreamWriteUTF8String(Stream: TStream; Value: UTF8String);
{Writes a UTF8 character string to a Stream}
var
n, i: longword;
begin
n:= Length(Value);
StreamWriteCardinal(Stream, n);
for i:= 0 to n-1 do
Stream.WriteBuffer(Value[i+1], SizeOf(UTF8Char));
end;
When an empty Value string is passed to the procedure, so that n, the string length, is zero, the bounds of the for loop control variable i should be 0 to -1. Therefore in this case the statement Stream.WriteBuffer inside the for loop should not be executed. This is because the termination test, i<= UpperBound, which should be executed before the loop body, should evaluate to False. It is my understanding that a for loop should be implemented in such a way that the body should be executed zero or more times depending on the bounds of the control variable tested before proceeding to the body.
However I am finding that in the case of n=0 the compiled code does not skip the statement Stream.WriteBuffer as one would expect, with the result that the Value[i+1] gives rise to an access violation exception.
Let me say that I have similar procedures for writing other types of string to a stream, most of which can handle a zero length string without any problem.
Can anyone suggest why in this case the loop does not appear to be working as it ought?
You have declared n as a LongWord, which is an unsigned integer of 32 bits.
Therefore, n - 1 will wrap around and be 4294967295.
You should use the Integer type instead, for both i and n. That's a 32-bit signed integer, so n - 1 will indeed be -1.

Delphi - join 2 integer in a Int64

I'm working with Delphi and Assembly, so, i had a problem. I used a instruction(RDTSC) in Assembly of getting a 64-bits read time-stamp, the instruction put the numbers separately in two registers EAX and EDX. But it's ok, i get it with Delphi Integer variables. But now, i need to join those variables in 1 of 64-bits. It's like:
Var1 = 46523
var2 = 1236
So i need to put it into one variable like:
Var3 = 465231236
it's like a StrCat, but i'm don't know how to do it. Somebody can help me?
You certainly don't want to concatenate the decimal string representations of the two values. That is not the way you are expected to combine the two 32 bit values returned from RTDSC into a 64 bit value.
Combining 46523 and 1236 should not yield 465231236. That is the wrong answer. Instead, you want to take the high order 32 bits, and put them alongside the low order 32 bits.
You are combining $0000B5BB and $00004D4. The correct answer is either $0000B5BB00004D4 or $00004D40000B5BB, depending on which of the two values are the high and low order parts.
Implement this in code, for instance, using Int64Rec:
var
Value: UInt64;
...
Int64Rec(Value).Lo := Lo;
Int64Rec(Value).Hi := Hi;
where Lo and Hi are the low and high 32 bit values returned by RTDSC.
So, bits 0 to 31 are set to the value of Lo, and bits 32 to 63 are set to the value of Hi.
Or it can be written using bitwise operations:
Value := (UInt64(Hi) shl 32) or UInt64(Lo);
If all you need to do is read the time stamp counter, then you don't need to do any of this though. You can implement the function like this:
function TimeStampCounter: UInt64;
asm
RDTSC
end;
The register calling convention requires that a 64 bit value return value is passed back to the caller in EDX:EAX. Since the RDTSC places the values in those exact registers (not a coincidence by the way), you have nothing more to do.
All of this said, rather than using the time stamp counter, it is usually preferable to use the performance counter, which is wrapped by TStopWatch from System.Diagnostics.
The simple way is to use a record
type
TMyTimestamp = record
case Boolean of
true:
( Value: Int64 );
false:
( Value1: Integer; Value2: Integer );
end;
and you can store/read each value as you like
var
ts: TMyTimestamp;
begin
ts.Value1 := 46523;
ts.Value2 := 1236;
WriteLn( ts.Value ); // -> 5308579624379
ts.Value := 5308579624379;
WriteLn( ts.Value1 ); // -> 46523
WriteLn( ts.Value2 ); // -> 1236
end;
see: Docwiki: Variant Parts in Records

Converting Integer number into hexadecimal number in delphi 7

Write a program to convert an integer number to its hexadecimal representation without using inbuilt functions.
Here is my code, but it is not working. Can anyone tell where is the mistake?
It is giving an error:
"Project raised exception class EAccessViolation with message 'Access violation at address 00453B7B in module 'Project.exe'.Write of address FFFFFFFF'.Process stopped.Use Step or Run to continue."
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,
Dialogs;
type
TForm1 = class(TForm)
end;
function hexvalue(num:Integer):Char;
var
Form1: TForm1;
implementation
{$R *.dfm}
function hexvalue(num:Integer):Char;
begin
case num of
10: Result:='A';
11: Result:='B';
12: Result:='C';
13: Result:='D';
14: Result:='E';
15: Result:='F';
else Result:=Chr(num);
end;
end;
var
intnumber,hexnumber,actualhex:String;
integernum:Integer;
i,j,k:Byte;
begin
InputQuery ('Integer Number','Enter the integer number', intnumber);
integernum:=StrToInt(intnumber);
i:=0;
while integernum >= 16 do
begin
hexnumber[i]:=hexvalue(integernum mod 16);
integernum:= integernum div 16;
Inc(i);
end;
hexnumber[i]:= hexvalue(integernum);
k:=i;
for j:=0 to k do
begin
actualhex[j]:= hexnumber[i];
Dec(i);
end;
ShowMessage(actualhex);
end.
Since this obviously is a homework assignment, I don't want to spoil it for you and write the solution, but rather attempt to guide you to the solution.
User input
In real code you would need to be prepared for any mistake from the user and check that the input really is integer numbers only and politely ask the user to correct the input if erroneous.
Conversion loop
You have got that OK, using mod 16 for each nibble of integernum and div 16 to move to the next nibble, going from units towards higher order values.
Conversion of nibble to hex character
Here you go wrong. If you would have written out also the cases for 0..9, you could have got the case statement right. As others have commented, Chr() takes an ASCII code. However, using a case statement for such a simple conversion is tedious to write and not very efficient.
What if you would have a lookup table (array) where the index (0..15) directly would give you the corresponding hex character. That would be much simpler. Something like
const
HexChars: array[_.._] of Char = ('0',_____'F')
I leave it to you to fill in the missing parts.
Forming the result (hex string)
Your second major mistake and the reason for the AV is that you did not set the length of the string hexnumber before attempting to acess the character positions. Another design flaw is that you fill in hexnumber backwards. As a result you then need an extra loop where you reverse the order to the correct one.
There are at least two solutions to solve both problems:
Since you take 32 bit integer type input, the hex representation is not more than 8 characters. Thus you can preset the length of the string to 8 and fill it in from the lower order position using 8 - i as index. As a final step you can trim the string if you like.
Don't preset the length and just concatenate as you go in the loop hexnumber := HexChars[integernum mod 16] + hexnumber;.
Negative values
You did not in any way consider the possibility of negative values in your code, so I assume it wasn't part of the task.
First mistake : String are 1 indexed. Meaning that the index of their first character is 1 and not 0. You initialize "i" to 0 and then try to set hexnumber[i].
Second mistake : Strings might be dynamic, but they don't grow automatically. If you try to access the first character of an empty string, it won't work. You need to call SetLength(HeXNumber, NumberOfDigits). You can calculate the number of digits this way :
NumberOfDigits := Trunc(Log16(integernum)) + 1;
Since Log16 isn't really something that exists, you can either use LogN(16,integernum) or (Log(IntegerNum) / Log(16)) depending on what is available in your version of Delphi.
Note that this might return an invalid value for very, very large value (high INT64 range) due to rounding errors.
If you don't want to go that road, you could replace the instruction by
hexnumber := hexvalue(integernum mod 16) + hexnumber;
which would also remove the need to invert the string at the end.
Third Mistake : Using unsigned integer for loop variable. While this is debatable, the instruction
for I := 0 to Count - 1 do
is common practice in Delphi without checking Count > 0. When count = 0 and using an unsigned loop counter, you'll either get an integer overflow (if you have them activated in your project options) or you'll loop High(I) times, which isn't what you want to be doing.
Fourth mistake : already mentionned : Result:=Chr(num) should be replaced by something like Result := InttoStr(Num)[1].
Personally, I'd implement the function using an array.
HexArr : Array[0..15] of char = ('0', '1',...,'D','E','F');
begin
if InRange(Num, 0, 15) then
Result := HexArr[Num]
else
//whatever you want
end;

How to get a 64-bit random value in Delphi?

How can I create a random 64-bit integer value in Delphi 2006? The built-in integer-based Random() function seems to return only values between 0 and 2^31.
You can use my GpRandomGen. It implements Marsaglia/Zaman/James algorithm, is extremely fast and supposedly very random. Released as a freeware.
Generate two 32 bit randoms and splice them together.
EDIT
Similar to #Andreas's answer I like the following (equivalent) implementation:
function Random64: UInt64;
var
Overlay: packed record
a, b: UInt32;
end absolute Result;
begin
Assert(SizeOf(Overlay)=SizeOf(Result));
Overlay.a := Random32;
Overlay.b := Random32;
end;
To answer my own question I came up with the following code:
function GetRandomInt64() : int64;
begin
Int64Rec(result).Words[0] := Random(High(Word));
Int64Rec(result).Words[1] := Random(High(Word));
Int64Rec(result).Words[2] := Random(High(Word));
Int64Rec(result).Words[3] := Random(High(Word));
end;
Not sure if this is a valid solution or it will always create the same follow-up number X+1 after a given result number X.
You can generate 64 random bits and interpret the result as an integer. (63 bits if you are working with signed integers and want the result to be non-negative.) Equivalently you can take two random integers in the range 0..2^31-1, plus two extra random bits, and concatenate them to get a random 64-bit integer.
EDIT: I was curious about the statistical properties of pseudo-random numbers generated by concatenating pseudo-random components and found that (apparently) this approach might not work well depending on your pseudo-random generator (of course for true random number generation, as from atmospheric noise, concatenating random bits is no problem). For recreational use, the loss of various statistical properties might be acceptable, but for more serious use you might end up needing a custom pseudo-random generator as #gabr suggested. Here is a related question: Best method of generating a number with 256 random bits?
Create a GUID (eg CoCreateGuid) and cast it to Int64.
Simple:
function Random64: UInt64;
begin
PCardinal(#result)^ := Random32;
PCardinal(cardinal(#result) + 4)^ := Random32;
end;
where Random32 is your favourite 32-bit unsigned integer random number function.

Resources