There is an invalid floating point operation, but where? - pascal

I'm currently writing a code the takes a number given a prints all the prime numbers that fit the format 4n+1. This is what I have so far. They problem is that this gives me a runtime error 207 which I think means invalid floating point operation, but I can't see how it ended up doing an invalid floating point operation. The only the code should be dealing with negative numbers in the line "if num-(iter*iter)> then".
program TwoSquares;
var
num, numSqrt, iter, bigSqr,smallSqr: integer;
begin
num:=29;
while num>4 do
begin
numSqrt:=trunc(sqrt(num));
for iter:=2 to numSqrt do
begin
if num mod iter = 0 then
num:=num - 1;
continue;
end;
if (num-1) mod 4 = 0 then
begin
iter:=(num-1) div 4;
while iter>0 do
begin
if num-(iter*iter)>0 then
bigSqr:=iter;
break;
iter:=iter-1;
end;
smallSqr:=trunc(sqrt(num-(iter*iter)));
writeln(num,' ', smallSqr,' ',bigSqr);
num:=num - 1;
end;
end;
end.

Your check is not directly before the place where it is used. Think; is the break; statement after that num-(iter*iter) if-then check the only way that while loop can terminate?
Try to single step your program, this can also verify if the block structure works as you think. It doesn't seem very consistent, with begin..end in some places, and indentation in others.

Related

So I need to sort alphabeticlly structure data in pascal, I improvised a sorting method, but has an error idk how to fix

sorting system and the main problem starts from the "Until" function. I would like to hear someones opinion about what I did wrong, and if there is an easier solution, I will appreciate if u told me about it.
The idea of the problem is: you have n number of people, and u need do introduce each one from the keyboard. Then, I need to sort them alphabeticlly
uses crt;
type Data = record
day : 1..31;
month : 1..12;
year : integer;
end;
Persoana = record
Name : string;
BirthDate : Data;
end;
ListaPersoane = array [1..50] of Persoana;
var x : ListaPersoane;
n:1..50;
i,z,j,l,a,v:integer;
y, k : longint;
aux : string;
begin
writeln('Program created on: 13/10/2020;');
writeln('give the number of people (max. 50):');
readln(n);
for i:=1 to n do begin
ClrScr;
writeln('Insert the name of person ', i, ': '); readln(x[i].Name);
writeln('Insert the date o birth:'); writeln('day:'); readln(x[i].BirthDate.day);
writeln('month:'); readln(x[i].BirthDate.month);
writeln('year:'); readln(x[i].BirthDate.year);
ClrScr;
end;
writeln('_______________________');
for i:=1 to n do begin
writeln(i, ') ', x[i].Name, ' ', x[i].BirthDate.day, '/', x[i].BirthDate.month, '/', x[i].BirthDate.year, ';');
writeln('_______________________');
end;
writeln();
repeat
k:=0;
for i:=1 to n do begin
j:=1;
repeat
Inc(j);
until (x[i].Name[j]>x[i].Name[j]) or (x[i].Name[j]<x[i].Name[j]);
if(x[i].Name[j]>x[i+1].Name[j]) then begin
aux:=x[i].Name;
x[i].Name:=x[i+1].Name;
x[i+1].Name:=aux;
z:=x[i].BirthDate.day;
x[i].BirthDate.day:=x[i+1].BirthDate.day;
x[i+1].BirthDate.day:=z;
l:=x[i].BirthDate.month;
x[i].BirthDate.month:=x[i+1].BirthDate.month;
x[i+1].BirthDate.month:=l;
a:=x[i].BirthDate.year;
x[i].BirthDate.year:=x[i+1].BirthDate.year;
x[i+1].BirthDate.year:=a;
Inc(k);
end;
end;
until (k=0);
writeln('_______________________');
for i:=1 to n do begin
writeln(i, ') ', x[i].Name, ' ', x[i].BirthDate.day, '/', x[i].BirthDate.month, '/', x[i].BirthDate.year, ';');
writeln('_______________________');
end;
writeln();
end.
I would expect that PascalABC can compare two strings and return which one is "smaller" or "bigger", without looping through the characters.
But to draw your attention to (at least) three issues in your sorting code, consider this code of yours:
j := 1;
repeat
Inc(j);
until (x[i].Name[j] > x[i].Name[j]) or (x[i].Name[j] < x[i].Name[j]);
Issue 1:
You initialize j := 1 before the loop. Then before you use j to index a character, you increment it. Thus you never attempt to compare the first character.
Issue 2:
Your repeat loop doesn't take into consideration that names have a limited, and often different length.
Issue 3:
Will either of these conditions, on the until row, ever be true:
(x[i].Name[j] > x[i].Name[j])
or this:
(x[i].Name[j] < x[i].Name[j])
In the subsequent code you correctly compare a character in x[i] with x[i+1]
I leave the correction of these errors for you, yourself, to correct. Consult with your tutor if needed.
You have a repeat .. until which terminates when k=0. You start with k assigned 0, then never change k. Perhaps your repeat is terminating because you don’t change k in the loop.

Reading A Variable As Both A Number And String of Words

I am trying to get Dep_Code to read as a string after choosing the options given (1, 2 or 3). I first had it set to integer in my first program (I think) and was able to get it to read out the options given as words (Accounts ACC or the others). However, it was accidentally deleted. I've tried various ways to get it even setting Dep_Code as a string but its not working and I keep getting a variety of errors. Btw, I'm not familiar with programming so I'm aware that the following code is quite incorrect... but I hope you all can help. Thank you!
REPEAT
writeln ('Please enter the Department Code:- ');
writeln;
writeln ('1. Accounts (ACC)');
writeln ('2. Human Resources (HR)');
writeln ('3. Operations (OP)');
writeln;
readln (Dep_Code);
IF Dep_Code = 1 THEN
Dep_Code := ('Accounts (ACC)')
ELSE IF Dep_Code = 2 THEN
Dep_Code := ('Human Resources(HR)')
ELSE IF Dep_Code = 3 THEN
Dep_Code := ('Operations (OP)');
UNTIL ((Dep_Code >= 1) AND (Dep_Code <= 3));
This is impossible. Pascal is a strictly typed language, and something cannot be an Integer and a string at the same time, and variables cannot change type either:
IF Dep_Code = 1 THEN
Dep_Code := ('Accounts (ACC)')
But you don't need a string at all. Keep it an integer. The functions that handle the various depts can write or define such strings, if necessary. Your logic for the menu does not need a string variable.
Do something like:
procedure HandleAccounts(var Error: Boolean);
begin
...
end;
// Skipped the other functions to keep this answer short ...
var
Dep_Code: Integer;
AllFine: Boolean;
// Skip the rest of the necessary code ...
repeat
// Skipped the Writelns to keep this answer short ...
Readln(Dep_Code);
Error := False;
case Dep_Code of
1: HandleAccounts(Error);
2: HandleHumanResources(Error);
3: HandleOperations(Error);
else
Error := True;
end;
until not Error;
Above, I skipped some of the code. You can fill in the blanks, I guess.

How to remove spaces from string with while do operator? Pascal

I have text and I need to remove spaces from beginning of text and from end of text. And I can do it only with while do operator. How can I do that? Here's program code
program RandomTeksts;
uses crt;
var
t:String;
l, x, y:Integer;
const tmin=1; tmax=30;
label
Start,
end;
begin
Start:
clrscr;
writeln('write text (from ',tmin,' to ',tmax,' chars): ');
readln(t);
l:=length(t);
if (l<tmin) or (l>tmax) then
begin
writeln('Text doesn't apply to rules!');
goto end;
end;
clrscr;
begin
randomize;
repeat
x:=random(52+1);
y:=random(80+1);
textcolor(white);
gotoxy(x,y);
writeln(t);
delay(700);
clrscr;
until keypressed;
end;
ord (readkey)<>27 then
goto Start;
end:
end.
Academic problem: Remove leading and trailing spaces from a string using a while loop.
How do we approach this problem?
Well, we certainly would like to create a function that trims a string. This way, we can simply call this function every time we need to perform such an operation. This will make the code much more readable and easier to maintain.
Clearly, this function accepts a string and returns a string. Hence its declaration should be
function Trim(const AText: string): string;
Here I follow the convention of prefixing arguments by "A". I also use the const prefix to tell the compiler I will not need to modify the argument within the function; this can improve performance (albeit very slightly).
The definition will look like this:
function Trim(const AText: string): string;
begin
// Compute the trimmed string and save it in the result variable.
end;
A first attempt
Now, let's attempt to implement this algorithm using a while loop. Our first attempt will be very slow, but fairly easy to follow.
First, let us copy the argument string AText to the result variable; when the function returns, the value of result will be its returned value:
result := AText;
Now, let us try to remove leading space characters.
while result[1] = ' ' do
Delete(result, 1, 1);
We test if the first character, result[1], is a space character and if it is, we use the Delete procedure to remove it from the string (specifically, Delete(result, 1, 1) removes 1 character from the string starting at the character with index 1). Then we do this again and again, until the first character is something other than a space.
For example, if result initially is ' Hello, World!', this will make it equal to 'Hello, World!'.
Full code, so far:
function Trim(const AText: string): string;
begin
result := AText;
while result[1] = ' ' do
Delete(result, 1, 1);
end;
Now try this with a string that consists only of space characters, such as ' ', or the empty string, ''. What happens? Why?
Think about it.
Clearly, in such a case, result will sooner or later be the empty string, and then the character result[1] doesn't exist. (Indeed, if the first character of result would exist, result would be of length at least 1, and so it wouldn't be the empty string, which consists of precisely zero characters.)
Accessing a character that doesn't exist will make the program crash.
To fix this bug, we change the loop to this:
while (Length(result) >= 1) and (result[1] = ' ') do
Delete(result, 1, 1);
Due to a technique known as 'lazy boolean evaluation' (or 'short-circuit evaluation'), the second operand of the and operator, that is, result[1] = ' ', will not even run if the first operand, in this case Length(result) >= 1, evaluates to false. Indeed, false and <anything> equals false, so we already know the value of the conjunction in this case.
In other words, result[1] = ' ' will only be evaluated if Length(result) >= 1, in which case there will be no bug. In addition, the algorithm produces the right answer, because if we eventually find that Length(result) = 0, clearly we are done and should return the empty string.
Removing trailing spaces in a similar fashion, we end up with
function Trim(const AText: string): string;
begin
result := AText;
while (Length(result) >= 1) and (result[1] = ' ') do
Delete(result, 1, 1);
while (Length(result) >= 1) and (result[Length(result)] = ' ') do
Delete(result, Length(result), 1);
end;
A tiny improvement
I don't quite like the space character literals ' ', because it is somewhat difficult to tell visually how many spaces there are. Indeed, we might even have a different whitespace character than a simple space. Hence, I would write #32 or #$20 instead. 32 (decimal), or $20 (hexadecimal), is the character code of a normal whitespace.
A (much) better solution
If you try to trim a string containing many million of characters (including a few million leading and trailing spaces) using the above algorithm, you'll notice that it is surprisingly slow. This is because we in every iteration need to reallocate memory for the string.
A much better algorithm would simply determine the number of leading and trailing spaces by reading characters in the string, and then in a single step perform a memory allocation for the new string.
In the following code, I determine the index FirstPos of the first non-space character in the string and the index LastPos of the last non-space character in the string:
function Trim2(const AText: string): string;
var
FirstPos, LastPos: integer;
begin
FirstPos := 1;
while (FirstPos <= Length(AText)) and (AText[FirstPos] = #32) do
Inc(FirstPos);
LastPos := Length(AText);
while (LastPos >= 1) and (AText[LastPos] = #32) do
Dec(LastPos);
result := Copy(AText, FirstPos, LastPos - FirstPos + 1);
end;
I'll leave it as an exercise for the reader to figure out the precise workings of the algorithm. As a bonus exercise, try to benchmark the two algorithms: how much faster is the last one? (Hint: we are talking about orders of magnitude!)
A simple benchmark
For the sake of completeness, I wrote the following very simple test:
const
N = 10000;
var
t: cardinal;
dur1, dur2: cardinal;
S: array[1..N] of string;
S1: array[1..N] of string;
S2: array[1..N] of string;
i: Integer;
begin
Randomize;
for i := 1 to N do
S[i] := StringOfChar(#32, Random(10000)) + StringOfChar('a', Random(10000)) + StringOfChar(#32, Random(10000));
t := GetTickCount;
for i := 1 to N do
S1[i] := Trim(S[i]);
dur1 := GetTickCount - t;
t := GetTickCount;
for i := 1 to N do
S2[i] := Trim2(S[i]);
dur2 := GetTickCount - t;
Writeln('trim1: ', dur1, ' ms');
Writeln('trim2: ', dur2, ' ms');
end.
I got the following output:
trim1: 159573 ms
trim2: 484 ms

How to forbid equal numbers

I started learning Pascal :) and I was interested on making a kind of Euromillion... However, I don't know how to forbid the same numbers or stars...
I thought this (below) would solve it... But it didn't... Help?
Program euromillion;
var num: array [1..5] of integer;
Procedure numbers;
var i, j: integer;
Begin
write ('Digite o número 1: ');
readln (num[1]);
for i:=2 to 5 do
for j:=1 to (i-1) do
Begin
repeat
write ('Digite o número ', i, ': ');
readln (num[i]);
until (num[i]>=1) and (num[i]<=50) and ((num[i]=num[j])=false);
End;
End;
Begin
numbers;
readln();
End.
Thanks guys :)
Although it is tempting to try and write a single block of code, as you have, it is better not to. Instead, a better way to write a program like this
is to think about splitting the task up into a number of procedures or functions
each of which only does a single part of the task.
One way to look at your task is to split it up into sub-tasks, as follows:
You prompt the user to enter a series of numbers
Once each number is entered, you check whether it is already in the array
If it isn't, you enter it in the array, otherwise prompt the user for another number
Once the array is filled, you output the numbers in the array
So, a key thing is that it would be helpful to have a function that checks whether
a new number is already in the array and returns True if it is and False otherwise. How to do that is the answer to your question.
You need to be careful about this because if you use the array a second time in the
program, you need to avoid comparing the new number with the array contents from
the previous time. I deliberately have not solved that problem in the example code below, to leave it as an exercise for the reader. Hint: One way would be to write a procedure which "clears" the array before each use of it, e.g. by filling it with numbers which are not valid lottery numbers, like negative numbers or zero. Another way would be to define a record which includes the NumberArray and a Count field which records how many numbers have been entered so far: this would avoid comparing the new number to all the elements in the
array and allow you to re-use the array by resetting the Count field to zero before calling ReadNumbers.
program LotteryNumbers;
uses crt;
type
TNumberArray = array[1..5] of Integer;
var
Numbers : TNumberArray;
Number : Integer;
function IsInArray(Number : Integer; Numbers : TNumberArray) : Boolean;
var
i : Integer;
begin
Result := False;
for i:= Low(Numbers) to High(Numbers) do begin
if Numbers[i] = Number then begin
Result := True;
break;
end;
end
end;
procedure ReadNumbers(var Numbers : TNumberArray);
var
i : Integer;
NewNumber : Integer;
OK : Boolean;
begin
// Note: This function needs to have a check added to it that the number
// the user enters is a valid lottery number, in other words that the
// number is between 1 and the highest ball number in the lottery
for i := Low(Numbers) to High(Numbers) do begin
repeat
OK := False;
writeln('enter a number');
ReadLn(NewNumber);
OK := not IsInArray(NewNumber, Numbers);
if not OK then
writeln('Sorry, you''ve already chosen ', NewNumber);
until OK;
Numbers[i] := NewNumber;
end;
end;
procedure ListNumbers(Numbers : TNumberArray);
var
i : Integer;
begin
for i := Low(Numbers) to High(Numbers) do
writeln(Numbers[i]);
end;
begin
ReadNumbers(Numbers);
ListNumbers(Numbers);
writeln('press any key');
readkey;
end.

how to fix exitcode 201?

I have a task to write a program in Pascal. When I run the program, the result was exitcode 201.
I don't know how to fix this error.
program convertTime;
uses crt;
Type
Jam = record
hh:integer ;
mm:integer ;
ss:integer;
end;
var
J : Jam;
P,totaldetik,sisa : integer;
begin
J.hh:= 16;
J.mm:= 10;
J.ss:= 34;
write('masukkan waktu(menit): ');read(p);
totaldetik:= (J.hh*3600) + (J.mm*60) + J.ss + (p*60);
J.hh:= totaldetik div 3600;
sisa:= totaldetik mod 3600 ;
J.mm:= sisa div 60;
J.ss:= sisa mod 60;
writeln('total the time: ',J.hh,' Hour ',J.mm,' Minute ',J.ss,' second');
readln;
end.
As seen in other questions, the error code 201 is a range check error. Put simply, a value's trying to be stored where it doesn't fit.
If, as in the linked question, you're using the Free Pascal Compiler, integer variables are 16-bit values – they can't go higher than
32,767.
Your totaldetik variable looks like it would often be higher than the limit for an integer value, so you'll need a larger variable to store it in. Try making totaldetik a longint instead.

Resources