Got "Boolean" expected "LongInt" pascal - boolean

I get this error on my insertion sort algorithm:
insertionsort.lpr(19,17) Error: Incompatible types: got "Boolean" expected "LongInt"
Here's the line 19 of my code
while j > 0 and A[j]>key do
I have tried googling all over the internet but i couldn't find any syntax errors or anything.
Here's the full code if it helps :
program instert;
uses crt;
const
N = 5;
var
i:integer;
j:integer;
key:integer;
A : Array[1..N] of Integer;
procedure insertionsort;
begin
for i := 2 to N do
begin
key := A[1];
j:= i - 1;
while j > 0 and A[j]>key do
begin
A[j+1] := A[j] ;
j := j-1;
end;
A[j+1] := key ;
end;
end;
begin
A[1]:= 9;
A[2]:= 6;
A[3]:= 7;
A[4]:= 1;
A[5]:= 2;
insertionsort;
end.
I also get the same error on the bubble sort algorithm i did. Here's the error line
bubblesort.lpr(26,14) Error: Incompatible types: got "Boolean" expected "LongInt"
Here's line 26 of my algorithm:
until flag = false or N = 1 ;
Here's the full code:
program bubblesort;
uses crt;
var
flag:boolean;
count:integer;
temp:integer;
N:integer;
A : Array[1..N] of Integer;
procedure bubblesort ;
begin
Repeat
flag:=false;
for count:=1 to (N-1) do
begin
if A[count] > A[count + 1] then
begin
temp := A[count];
A[count] := A[count + 1];
A[count] := temp;
flag := true;
end;
end;
N := N - 1;
until flag = false or N = 1 ;
end;
begin
A[1]:= 9;
A[2]:= 6;
A[3]:= 7;
A[4]:= 1;
A[5]:= 2;
N := 5;
bubblesort;
end.

In Pascal, boolean operators and and or have higher precedence than the comparison operators >, =, etc. So in the expression:
while j > 0 and A[j] > key do
Given that and has higher precedence, Pascal sees this as:
while (j > (0 and A[j])) > key do
0 and A[j] are evaluated as a bitwise and (since the arguments are integers) resulting in an integer. Then the comparison, j > (0 and A[j]) is evaluated as a boolean result, leaving a check of that with > key, which is boolean > longint. You then get the error that a longint is expected instead of the boolean for the arithmetic comparison.
The way to fix it is to parenthesize:
while (j > 0) and (A[j] > key) do ...
The same issue applies with this statement:
until flag = false or N = 1 ;
which yields an error because or is higher precedence than =. So you can parenthesize:
until (flag = false) or (N = 1);
Or, more canonical for booleans:
until not flag or (N = 1); // NOTE: 'not' is higher precedence than 'or'
When in doubt about the precedence of operators, parenthesizing is a good idea, as it removes the doubt about what order operations are going to occur.

Related

Function to return N significant digits of given number

I have seen several questions on this topic, but the answers do not seem useful to me.
I must create a function in PostgreSQL 10.5 that returns a number with N significant digits. I have tried different solutions for this problem, however I have a problem with a particular case. Below the example, where nmNumber is the number of the input parameters and nmSf is the number of significant digits.
SELECT round(nmNumber * power(10, nmSf-1-floor(log(abs(nmNumber ))))) / power(10, nmSf-1-floor(log(abs(nmNumber)))) result1,
round(nmNumber, cast(-floor(log(abs(nmNumber))) as integer)) result2,
floor(nmNumber / (10 ^ floor(log(nmNumber) - nmSf + 1))) * (10 ^ floor(log(nmNumber) - nmSf + 1)) result3;
If nmNumber = 0.0801 and nmSf = 2 then:
result 1 = 0.08; result2 = 0.08; result 3 = 0.08
The three results are incorrect given that:
The zeros immediately after the decimal point are not significant digits.
All non-zero digits are significant.
The zeros after digits other than zero in a decimal are significant.
According to point 3, the correct result of the previous example is: 0.080 and not 0.08 and although mathematically it turns out to be the same, visually I must obtain this result. Some idea of ​​how I can solve my problem? I suppose that returning a VARCHAR in exchange for a NUMERIC is part of the solution to be proposed.
Some idea or I'm missing something. Thank you.
This would implement what you ask for:
CREATE OR REPLACE FUNCTION f_significant_nr(_nr numeric, _sf int, OUT _nr1 text) AS
$func$
DECLARE
_sign bool; -- record negative sign
_int int; -- length of integral part
_nr_text text; -- intermediate text state
BEGIN
IF _sf < 1 THEN
RAISE EXCEPTION '_sf must be > 0!';
ELSIF _nr IS NULL THEN
RETURN; -- returns NULL
ELSIF _nr = 0 THEN
_nr1 := '0'; RETURN;
ELSIF _sf >= length(translate(_nr::text, '-.','')) THEN -- not enough digits, optional shortcut
_nr1 := _nr; RETURN;
ELSIF abs(_nr) < 1 THEN
_nr1 := COALESCE(substring(_nr::text, '^.*?[1-9]\d{' || _sf-1 || '}'), _nr::text); RETURN;
ELSIF _nr < 0 THEN -- extract neg sign
_sign := true;
_nr := _nr * -1;
END IF;
_int := trunc(log(_nr))::int + 1; -- <= 0 was excluded above!
IF _sf < _int THEN -- fractional digits not touched
_nr1 := rpad(left(_nr::text, _sf), _int, '0');
ELSE
_nr1 := trunc(_nr)::text;
IF _sf > _int AND (_nr % 1) > 0 THEN -- _sf > _int and we have significant fractional digits
_nr_text := right((_nr % 1)::text, -1); -- remainder: ".123"
_nr1 := _nr1 || COALESCE(substring(_nr_text, '^.*?[1-9]\d{' || (_sf - _int - 1)::text || '}'), _nr_text);
END IF;
END IF;
IF _sign THEN
_nr1 := '-' || _nr1;
END IF;
END
$func$ LANGUAGE plpgsql;
db<>fiddle here - with test case.
Deals with everything you throw at it, incl NULL, 0, 0.000 or negative numbers.
But I have doubts about your point 3 as commented.
postgres knows how to do that (even point 3), you just need to ask it the right way.
create or replace function
sig_fig(num numeric,prec int) returns numeric
language sql as
$$
select to_char($1, '9.'||repeat('9',$2-1)||'EEEE')::numeric
$$;
That creates a format string producing scientific
notation with a 3 digit mantissa. Uses that that
to get the number as text Then converts that back to numeric yielding a conventional number with that many significant figures.
demo:
with v as ( values (3.14159),(1234567),(0.02),(1024),(42),(0.0098765),(-6666) ) select column1 ,sig_fig(column1,3) as "3sf" from v;
column1 | 3sf
-----------+---------
3.14159 | 3.14
1234567 | 1230000
0.02 | 0.0200
1024 | 1020
42 | 42.0
0.0098765 | 0.00988
-6666 | -6670
(7 rows)

Rewrite long xor statement

Look at the following statement. c_r gets assigned an xor versioned of all c[k].
always_ff # (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= c[k][0] ^ c[k][1] ^ c[k][2] ^ c[k][3] ^ c[k][4] ^ c[k][5] ^ c[k][6] ^ c[k][7] ^ c[k][8] ^ c[k][9] ^ c[k][10] ^ c[k][11] ^ c[k][12] ^ c[k][13] ^ c[k][14] ^ c[k][15];
end
The design works, however is there a possibility to refactor the statement for easier maintenance and readability?
Note: c is defined as logic [7:0] c[16][16];
I would propose the following:
logic [16*8-1:0] c_r, next_c_r;
logic [7:0] c[16][16];
always_comb begin
next_c_r = '0;
foreach(c[idx0,idx1]) begin
next_c_r[idx0*8 +: 8] ^= c[idx0][idx1];
end
end
always_ff # (posedge clk_i)
begin
c_r <= next_c_r;
end
The foreach will iterate through all selected indexes. See IEEE Std 1800-2012 § 12.7.3 The foreach-loop for full syntax usage and functionality. ^= is a binary bitwise assignment operators, refer to IEEE Std 1800-2012 § 11.4 Operator descriptions. There are various code examples for foreach and ^= throughout the LRM.
You could try using a for loop inside to compute the XOR result and assign that to the c_r slice:
always_ff # (posedge clk_i)
begin
for(int k = 0; k < 16; k++) begin
logic [7:0] xor_result;
for (int i = 0; i < 16; i++)
xor_result ^= c[k][i];
c_r[k*8 +: 8] <= xor_result;
end
end
I'm not sure how well this will synthesize with your tool, but I've seen my colleagues use these kind of tricks (in VHDL) all the time.
Reduction operators are useful for this, a short example:
wire result;
wire [3:0] bus;
//assign result = bus[0] ^ bus[1] ^ bus[2] ^ bus[3];
assign result = ^bus;
So the unary ^ collapses the bus to a single bit, this also works for & and |.
In your case I believe that this should work:
always_ff # (posedge clk_i)
begin
for(k = 0; k < 16; k++)
c_r[k*8 +: 8] <= ^c[k];
end
If this is not possible embedding a second loop (which is extracted to a combinatorial section):
logic [15:0] parity_bus;
always_comb begin
for(k = 0; k < 16; k++) begin
parity_bus[k] = 1'b0;
for(int i = 0; i < 16; i++) begin
parity_bus[k] = parity_bus[k] ^c[k][i];
end
end
end
always_ff # (posedge clk_i) begin
for(k = 0; k < 16; k++) begin
c_r[k*8 +: 8] <= parity_bus[k];
end
end
You are effectively describing 16 sets of XOR logic in parallel.

Reduce length of the pseudo-encrypt function ouput

i have a question about the pseudo-encrypt function for postgres.
Is there any way that I can reduce the output to 6? I really like this function and want to use it, but only need a output between 1 and 999999.
This question is related to my last question. I want to use it to created unqiue numbers between 1 and 999999.
Thank you.
Use mod on the generated value to generate number in range from start_value to end_value:
select start_value + mod(pseudo_encrypt(number), end_value - start_value + 1);
For your case this will be look like:
select 1 + mod(pseudo_encrypt(23452), 999999);
It's not quite straightforward to set an upper bound of 999999, as the algorithm operates on blocks of bits, so it's hard to get away from powers of two.
You can work around this by cycle walking - just try encrypt(n), encrypt(encrypt(n)), encrypt(encrypt(encrypt(n)))... until you end up with a result in the range [1,999999]. In the interest of keeping the number of iterations to a minimum, you want to adjust the block size to get you as close to this range as possible.
This version will let you specify a range for the input/output:
CREATE OR REPLACE FUNCTION pseudo_encrypt(
value INT8,
min INT8 DEFAULT 0,
max INT8 DEFAULT (2^62::NUMERIC)-1
) RETURNS INT8 AS
$$
DECLARE
rounds CONSTANT INT = 3;
L INT8[];
R INT8[];
i INT;
blocksize INT;
blockmask INT8;
result INT8;
BEGIN
max = max - min;
value = value - min;
IF NOT ((value BETWEEN 0 AND max) AND (max BETWEEN 0 AND 2^62::NUMERIC-1)) THEN
RAISE 'Input out of range';
END IF;
blocksize = ceil(char_length(ltrim(max::BIT(64)::TEXT,'0'))/2.0);
blockmask = (2^blocksize::NUMERIC-1)::INT8;
result = value;
LOOP
L[1] = (result >> blocksize) & blockmask;
R[1] = result & blockmask;
FOR i IN 1..rounds LOOP
L[i+1] = R[i];
R[i+1] = L[i] # ((941083981*R[i] + 768614336404564651) & blockmask);
END LOOP;
result = (L[rounds]::INT8 << blocksize) | R[rounds];
IF result <= max THEN
RETURN result + min;
END IF;
END LOOP;
END;
$$
LANGUAGE plpgsql STRICT IMMUTABLE;
I can't guarantee its correctness, but you can easily show that it maps [1,999999] back to [1,999999]:
SELECT i FROM generate_series(1,999999) s(i)
EXCEPT
SELECT pseudo_encrypt(i,1,999999) FROM generate_series(1,999999) s(i)

Maple: RNG is not random

i was "finding Pi" with Monte Carlo Method, but the answer was incorrect. The oryginal code was:
RandomTools[MersenneTwister]: with(Statistics):
tries := 10000:
s := 0;
for i to tries do
if GenerateFloat()^2+GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
It gives answer aroud 2.8-2.85
when I change the code to
s := 0;
x := Array([seq(GenerateFloat(), i = 1 .. tries)]);
y := Array([seq(GenerateFloat(), i = 1 .. tries)]);
for i to tries do
if x[i]^2+y[i]^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
Then the answer is correct. I have no idea why i can't generate number in "for" loop.
I've founded that the mean of it is the same, but the variance is different.
For:
tries := 100000;
A := Array([seq(GenerateFloat(), i = 1 .. 2*tries)]);
s1 := Array([seq(A[i]^2+A[tries+i]^2, i = 1 .. tries)]);
Mean(s1);
Variance(s1);
s2 := Array([seq(GenerateFloat()^2+GenerateFloat()^2, i = 1 .. tries)]);
Mean(s2);
Variance(s2);
output is:
0.6702112097021581
0.17845439723457215
0.664707674135025
0.35463131700965245
What's wrong with it? GenerateFloat() should be as uniform as possible.
Automatic simplification is turning your,
GenerateFloat()^2+GenerateFloat()^2
into,
2*GenerateFloat()^2
before GenerateFloat() is evaluated.
One simple change to get it to work as you expected would be separate them. Eg,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
for i to tries do
t1,t2 := GenerateFloat(),GenerateFloat();
if t1^2+t2^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
Another way is to use a slightly different construction which doesn't automatically simplify. Consider, single right quotes (uneval quotes) don't stop automatic simplification (which is a definition of the term if you want).
'f()^2 + f()^2';
2
2 f()
But the following does not automatically simplify,
a:=1:
'f()^2 + a*f()^2';
2 2
f() + a f()
Therefore another easy workaround is,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
a := 1;
for i to tries do
if GenerateFloat()^2 + a*GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);

How to convert integer to hex notation?

Using: Firebird 2.5.3
In a stored procedure (PSQL), converting a number from hex notation to decimal notation is done easily:
DECLARE VARIABLE I INTEGER;
BEGIN
I = CAST('0x0FFFE' AS INTEGER); -- I will have the value 65534
How can the reverse be achieved? ie. Convert from decimal notation to hex notation?
Short of using a UDF (which would mean using an external library file), the solution is to write a stored procedure to accomplish this:
SET TERM ^^ ;
CREATE PROCEDURE INTTOHEX (
INPUTNUMBER BigInt)
returns (
OUTPUTNUMBER VarChar(8))
AS
DECLARE VARIABLE Q BigInt;
DECLARE VARIABLE R BigInt;
DECLARE VARIABLE T BigInt;
DECLARE VARIABLE H VARCHAR(1);
DECLARE VARIABLE S VARCHAR(6);
begin
/* Max input value allowed is: 4294967295 */
S = 'ABCDEF';
Q = 1;
OUTPUTNUMBER = '';
T = INPUTNUMBER;
WHILE (Q <> 0) DO
BEGIN
Q = T / 16;
R = MOD(T, 16);
T = Q;
IF (R > 9) THEN
H = SUBSTRING(S FROM (R-9) FOR 1);
ELSE
H = R;
OUTPUTNUMBER = H || OUTPUTNUMBER ;
END
SUSPEND;
end ^^
SET TERM ; ^^
You can call this stored procedure from standard SQL or another stored procedure like this:
For example:
SELECT OUTPUTNUMBER FROM INTTOHEX(65534);
just did a short firebird function,
could handle bigger number,
maybe could help someone
CREATE OR ALTER FUNCTION INT64TOHEX (
C BIGINT)
RETURNS VARCHAR(32)
AS
DECLARE VARIABLE IREM INTEGER;
DECLARE VARIABLE HEX VARCHAR(32);
BEGIN
IREM = MOD(C, 0XFF);
HEX = '';
WHILE (IREM > 0) DO
BEGIN
HEX = SUBSTRING('0123456789abcdef' FROM BIN_SHR(BIN_AND(C, 0XFF), 4) + 1 FOR 1) || SUBSTRING('0123456789abcdef' FROM BIN_AND(BIN_AND(C, 0XFF), 15) + 1 FOR 1) || HEX;
C = BIN_SHR(C, 8);
IREM = MOD(C, 0XFF);
END
RETURN TRIM(HEX);
END