Invalid Floating point operation Pascal - pascal

I'm coding a program with Pascal in fastreport, The problem appear when I try to show the result of a division. this is my program:
var
relec_tp_for_pa, tp_for_pa, relec_tt_tp, total_tp, coef_relec : Real = 0;
relec_vt : Integer = 0;
procedure MasterData1OnBeforePrint(Sender: TfrxComponent);
begin
if ( ( <EJobsQuery."SERV_ID"> = 54 ) ) then
begin
relec_tp_for_pa := tp_for_pa;
relec_vt := relec_vt + <EJobsQuery."EJOB_VOLUME">;
relec_tt_tp := relec_tt_tp + tp;
total_tp := total_tp + tp;
end;
coef_relec := StrToFloat(FormatFloat('0.0000', relec_tt_tp / total_tp));
relec_pa.Text := FormatFloat('0.00', relec_vt /(relec_tp_for_pa * coef_relec));
relec_pr.Text := FloatToStr( relec_vt / relec_tt_tp );
end;
Both of this divisions:
-relec_vt /(relec_tp_for_pa * coef_relec)
-relec_vt / relec_tt_tp
are giving me the error : Invalid Floating point operation
I'm coding in the FastReport 4.11.4 a report.
under 32 bits OS if this can help.
Thanks again.

From what you've coded it seems that You divide by zero!
-relec_vt /(relec_tp_for_pa * coef_relec)
-relec_vt / relec_tt_tp
Since
relec_tp_for_pa := tp_for_pa
is definetly ZERO!
relec_tp_for_pa * coef_relec
Will also be zero!
For relec_tt_tp I just can try to guess, since this code is not a complete example.
total_tp := total_tp + tp
total_tp is zero, and if tp is also zero You'd end up in a division by zero.
Generally I'd always check if your divisor is not zero!

Related

Read integers from a string

I'm learning algorithms and I'm trying to make an algorithm that extracts numbers lets say n in [1..100] from a string. Hopefully I get an easier algorithm.
I tried the following :
procedure ReadQuery(var t : tab); // t is an array of Integer.
var
x,v,e : Integer;
inputs : String;
begin
//readln(inputs);
inputs:='1 2 3';
j:= 1;
// make sure that there is one space between two integers
repeat
x:= pos(' ', inputs); // position of the space
delete(inputs, x, 1)
until (x = 0);
x:= pos(' ', inputs); // position of the space
while x <> 0 do
begin
x:= pos(' ', inputs); //(1) '1_2_3' (2) '2_3'
val(copy(inputs, 1, x-1), v, e); // v = value | e = error pos
t[j]:=v;
delete(inputs, 1, x); //(1) '2_3' (2) '3'
j:=j+1; //(1) j = 2 (2) j = 3
//writeln(v);
end;
//j:=j+1; // <--- The mistake were simply here.
val(inputs, v, e);
t[j]:=v;
//writeln(v);
end;
I get this result ( resolved ) :
1
2
0
3
expected :
1
2
3
PS : I'm not very advanced, so excuse me for reducing you to basics.
Thanks for everyone who is trying to share knowledge.
Your code is rather inefficient and it also doesn't work for strings containing numbers in general.
A standard and performant approach would be like this:
type
TIntArr = array of Integer;
function GetNumbers(const S: string): TIntArr;
const
AllocStep = 1024;
Digits = ['0'..'9'];
var
i: Integer;
InNumber: Boolean;
NumStartPos: Integer;
NumCount: Integer;
procedure Add(Value: Integer);
begin
if NumCount = Length(Result) then
SetLength(Result, Length(Result) + AllocStep);
Result[NumCount] := Value;
Inc(NumCount);
end;
begin
InNumber := False;
NumCount := 0;
for i := 1 to S.Length do
if not InNumber then
begin
if S[i] in Digits then
begin
NumStartPos := i;
InNumber := True;
end;
end
else
begin
if not (S[i] in Digits) then
begin
Add(StrToInt(Copy(S, NumStartPos, i - NumStartPos)));
InNumber := False;
end;
end;
if InNumber then
Add(StrToInt(Copy(S, NumStartPos)));
SetLength(Result, NumCount);
end;
This code is intentionally written in a somewhat old-fashioned Pascal way. If you are using a modern version of Delphi, you wouldn't write it like this. (Instead, you'd use a TList<Integer> and make a few other adjustments.)
Try with the following inputs:
521 cats, 432 dogs, and 1487 rabbits
1 2 3 4 5000 star 6000
alpha1beta2gamma3delta
a1024b2048cdef32
a1b2c3
32h50s
5020
012 123!
horses
(empty string)
Make sure you fully understand the algorithm! Run it on paper a few times, line by line.

Find block number and floor by flat number

Imagine - there's a house with 80 flats. It has 4 floors and 5 blocks. Each block has 4 flats.
User is asked to input flat number and Pascal program is supposed to calculate and output flat number. This must be calculated using some kind of formula. The only tip I have is that I have to use div and mod operations.
This is how the house looks like -
So far, I've created program, that loops through all 80 flats and after each 16 flats increases block value and after each 4 blocks increases stair.
This is my code:
program project1;
var
i, floors, blocks, flats, flat, block, floor, blockCounter, floorCounter : integer;
begin
floors := 4;
blocks := 5;
flats := 80;
while true do
begin
write('Flat number: ');
read(flat);
block := 1;
floor := 1;
blockCounter := 0;
floorCounter := 0;
for i := 1 to 80 do
begin
blockCounter := blockCounter + 1;
floorCounter := floorCounter + 1;
if (floorCounter = 4) then
begin
floorCounter := 0;
floor := floor + 1;
end;
if (blockCounter > 16) then
begin
block := block + 1;
blockCounter := 0;
floorCounter := 0;
floor := 1;
end;
if (i = flat) then
begin
writeln('Flat nr. ', flat, ' is in ', floor, '. floor and in ', block, '. block!');
end;
end;
end;
end.
Is there anyone who can help me with this?
I've finally solved my problem myself.
I finally undersood how div works, so I was able to solve this.
program Maja;
var dzivoklis, kapnutelpa, stavs : integer;
begin
while true do
begin
write('Ievadi dzivokla numuru: ');
read(dzivoklis);
kapnutelpa := ((dzivoklis - 1) div 16) + 1;
stavs := (((dzivoklis - 1) mod 16) div 4) + 1;
writeln('Kapnutelpa: ', kapnutelpa);
writeln('Stavs: ', stavs);
writeln();
end;
end.

PL/SQL Check Digit, luhn using MOD 11

So here is the question:
Write code to take in an id and determine if the check digit is correct
UPDATED CODE:
Set SERVEROUTPUT ON
DECLARE
val_num NUMBER := '&user_input';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num*10);
for x in 1..length(conv_string) loop
y := to_number(substr(conv_string, -x, 1));
if mod(x,2) = 0 then
y := y * 2;
if y > 9 then
y := y - 9;
end if;
end if;
holder := holder + y;
end loop;
dbms_output.put_line ('Check is '||(11-Mod(holder, 11)));
END luhn;
/
SET SERVEROUTPUT ON
The return is:
SQL> # loop
Enter value for user_input: 036532
old 2: val_num NUMBER := '&user_input';
new 2: val_num NUMBER := '036532';
Check is 2
It should be 6
Before actual execution
SET SERVEROUTPUT ON
to enable SQL*Plus to fetch database output buffer.
Here is solution: https://community.oracle.com/thread/837639?start=0&tstart=0
There are lots of different variations of the luhn algorithm, so looking at these implementations and your (I think incomplete) description in the comments I think this may be fairly close to what you are looking for, and gives the correct checksum for 036532 as per your initial question.
Hope it is helpfull
Set SERVEROUTPUT ON
DECLARE
val_num number := '036532';
holder NUMBER := 0;
y NUMBER := 0;
conv_string VARCHAR2(20);
BEGIN
conv_string := to_char(val_num);
FOR X IN 1..LENGTH(CONV_STRING) LOOP
Y := TO_NUMBER(SUBSTR(CONV_STRING, -X, 1));
IF ((X+1) > 10) THEN
Y := Y * 10;
ELSE
Y := Y * (X + 1);
END IF;
IF (Y >= 10) THEN
HOLDER := HOLDER + TO_NUMBER(substr(TO_CHAR(Y), 1, 1)) + TO_NUMBER(substr(TO_CHAR(Y), 2, 1));
ELSE
HOLDER := HOLDER + Y;
END IF;
END LOOP;
HOLDER := MOD(HOLDER, 11);
Holder := 11 - mod(holder, 11);
dbms_output.put_line ('Check is '|| holder);
END luhn;
/
SET SERVEROUTPUT ON

A game with 100 oponnents, win as much money as possible

You play a game with 100 opponents. The game has k rounds. Every round you can eliminate some opponents (always atleast 1). You are rewarded for eliminating them.
The reward is: 100.000 * '# of eliminated opponents' / '# of opponents' <= in integers (rounded down)
I want to eliminate the opponents in a way, that gets me the largest amount of money possible.
Example game:
number of rounds = 3
first round we eliminate 50 opponents, so we get 100.000 * 50 / 100 = +50.000
second round we eliminate 30, so we get 100.000 * 30 / 50 = +60.000
last round we eliminate last 20 opponents, so we get 100.000 * 20 / 20 = +100.000
so the total winnings are: 210.000
I tried to write up something, but I don't think it's the most effective way to do it?
Program EliminationGame;
var
selectedHistory : array [1..10] of integer;
opponentCount,roundCount : integer;
maxOpponents,numberSelected : integer;
totalMoney : integer;
i : integer;
begin
totalMoney := 0;
maxOpponents := 100;
opponentCount := maxOpponents;
roundCount := 3; {test value}
for i:=1 to roundCount do begin
if (i = roundCount) then begin
numberSelected := opponentCount;
end else begin
numberSelected := floor(opponentCount / roundCount);
end;
selectedHistory[i] := numberSelected;
totalMoney := floor(totalMoney + (numberSelected / opponentCount * 100000));
opponentCount := opponentCount - numberSelected;
end;
writeln('Total money won:');
writeln(totalMoney);
writeln('Amount selected in rounds:');
for i:= 0 to Length(selectedHistory) do
write(selectedHistory[i],' ');
end.
Also it seems that floor function does not exist in pascal?
It seems the question has a maths answer that can be calculated in advance. As #Anton said it was obvious that the number of points given during the third round did not depend upon the number of eliminated enemies. So the third round should eliminate 1 enemy.
So We get the following function for a thre-round game.
f(x)=100000x/100+100000(99-x)/(100-x)+100000*1/1, where x- the number
of enemies eleminated at first round.
if we find the extrema (local maximum of the function) it appears equal to 90. That means the decision is the following: the first round eliminates 90 the second - 9, the third - 1 enemy.
Of course, for consideration: 90=100-sqrt(100).
In other words: the Pascal decision of the task is to loop a variable from 1 to 99 and see the maximum of this function. X-will be the answer.
program Project1;
var
x, xmax: byte;
MaxRes, tmp: real;
begin
xmax := 0;
MaxRes := 0;
for x := 1 to 99 do
begin
tmp := 100000 * x / 100 + 100000*(99 - x) / (100 - x) + 100000 * 1 / 1;
if tmp > MaxRes then
begin
MaxRes := tmp;
xmax := x;
end;
end;
writeln(xmax);
readln;
end.
The general decision for other number of enemies and rounds (using recursion) is the following (Delphi dialect):
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
Uses System.SysUtils;
var
s: string;
function Part(RemainingEnemies: byte; Depth: byte;
var OutputString: string): real;
var
i: byte;
tmp, MaxRes: real;
imax: byte;
DaughterString: string;
begin
OutputString := '';
if Depth = 0 then
exit(0);
imax := 0;
MaxRes := 0;
for i := 1 to RemainingEnemies - Depth + 1 do
begin
tmp := i / RemainingEnemies * 100000 + Part(RemainingEnemies - i, Depth - 1,
DaughterString);
if tmp > MaxRes then
begin
MaxRes := tmp;
imax := i;
OutputString := inttostr(imax) + ' ' + DaughterString;
end;
end;
result := MaxRes;
end;
begin
writeln(Part(100, 3, s):10:1);//first parameter-Enemies count,
//2-Number of rounds,
//3-output for eliminated enemies counter
writeln(s);
readln;
end.
This problem can be solved with a dynamic approach.
F(round,number_of_opponents_remained):
res = 0
opp // number_of_opponents_remained
for i in [1 opp]
res = max(res, opp/100 + F(round-1,opp - i) )
return res
I should say this not the complete solution and you add some details about it, and I am just giving you an idea. You should add some details such as base case and checking if opp>0 and some other details. The complexity of this algorithm is O(100*k).

Why do these 2 oracle functions perform differently?

I wrote a function in Oracle to convert IP addresses to integers. It seemed slow. I wrote a second function to do the same thing only faster. Unfortunately it ended up slower and I do not know why.
Original function;
FUNCTION GET_IP_INTEGER
(
IP_IN IN VARCHAR2
) RETURN NUMBER AS
DOT_COUNTER INTEGER;
CURRENT_DOT INTEGER;
LAST_DOT INTEGER := 1;
CURRENT_INTEGER INTEGER := 0;
OUTPUT_INTEGER INTEGER := 0;
BEGIN
FOR DOT_COUNTER IN 1..3
LOOP
CURRENT_DOT := INSTR(IP_IN,'.',LAST_DOT);
CURRENT_INTEGER := TO_NUMBER(SUBSTR(IP_IN,LAST_DOT,CURRENT_DOT - LAST_DOT));
LAST_DOT := CURRENT_DOT + 1;
CASE DOT_COUNTER
WHEN 1 THEN CURRENT_INTEGER := CURRENT_INTEGER * 16777216;
WHEN 2 THEN CURRENT_INTEGER := CURRENT_INTEGER * 65536;
WHEN 3 THEN CURRENT_INTEGER := CURRENT_INTEGER * 256;
END CASE;
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
CURRENT_INTEGER := 0;
END LOOP;
CURRENT_INTEGER := TO_NUMBER(SUBSTR(IP_IN,LAST_DOT));
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
RETURN OUTPUT_INTEGER;
END GET_IP_INTEGER;
It picks everything apart and works well. But I thought I could do better so I wrote this;
FUNCTION GET_IP_INTEGER1
(
IP_IN IN VARCHAR2
) RETURN NUMBER AS
OCTET_COUNTER INTEGER;
CURRENT_INTEGER INTEGER := 0;
OUTPUT_INTEGER INTEGER := 0;
BEGIN
FOR OCTET_COUNTER IN 1..4
LOOP
CURRENT_INTEGER := TO_NUMBER(REGEXP_SUBSTR(IP_IN,'\w+',1,OCTET_COUNTER));
CURRENT_INTEGER := POWER(2,24 - ((OCTET_COUNTER-1)*8)) * CURRENT_INTEGER;
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
END LOOP;
RETURN OUTPUT_INTEGER;
END GET_IP_INTEGER1;
This also works but seems to run much (about twice as long) slower. I would assume that either the power function or the regexp_substr is a pig. But I was hoping someone with more knowledge might point out which, and/or why.
Here is my little piece of knowledge: in oracle 11g, you have the hierarchical PL/SQL profiler. This will show you where your pl/sql is spending its time.
regexp_substr will be slower than a regular substr, and there will be a bit of overhead with the power. The most time would in in the regexp_substr though.
im curious why you say they are "slow" though. i assume you mean over a LOT of calls? as the routines are pretty snappy when i tested them.
Also, this type of function would benefit greatly from native compilation (which is easy to do in 11g, as the dba doesn't have to do anything to get this working).
finally you may find this to be marginally quicker (esp with native compilation).
create or replace function get_ip_integer3(ip_in in varchar2)
return integer
as
result integer := 0;
begin
result := result + 16777216 * substr(ip_in, 1, instr(ip_in, '.') - 1);
result := result +
65536 * substr(ip_in, instr(ip_in, '.') + 1,
instr(ip_in, '.', 1, 2) - instr(ip_in, '.') - 1);
result := result +
256 * substr(ip_in, instr(ip_in, '.', 1, 2) + 1,
instr(ip_in, '.', 1, 3) - instr(ip_in, '.', 1, 2) - 1);
result := result + substr(ip_in, instr(ip_in, '.', 1, 3) + 1);
return result;
end get_ip_integer3;

Resources