How to compute The First 8 Square Numbers by using loop in Oracle?
declare
total integer;
i integer;
begin
total := 0;
i := 1;
loop
total := total *i;
i := i*total;
exit when i > 8;
end loop;
dbms_output.put_line('the total is ' || total); end;
Please examine carefully this fragment:
i := 1;
loop
total := total *i;
i := i*total;
exit when i > 8;
end loop;
There is exit when i > 8; command that is supposed to exit the loop when i is greater than 8, but i is always 1 within the loop, so the loop is infinite and you never get any result.
You must increment i somwhere in the loop using i := i + 1; instruction.
This is not for your homework, but provides a solution for the question.
SELECT LEVEL * LEVEL squares
FROM DUAL
CONNECT BY LEVEL <= 8;
Output:
1
4
9
16
25
36
49
64
Related
I can't display the final output once the user has entered a negative number.
I tried creating a program that will ask the user for numbers continuously. If the user enters a negative number, the program will stop running and will display the total, average, number of zeroes entered, highest and lowest number. Below is my written code:
SET SERVEROUTPUT ON;
DECLARE
n NUMBER(3);
total NUMBER(3) := 0;
numZeros NUMBER(3) := 0;
average NUMBER(3);
highest NUMBER(3) := 0;
lowest NUMBER(3) := 0;
BEGIN
LOOP
n := &n;
total := total + n;
IF n = 0 THEN
numZeros := numZeros + 1;
ELSIF n > highest THEN
high := n;
ELSIF n < lowest THEN
low := n;
END IF;
EXIT WHEN n < 0;
END LOOP;
average := total / n;
DBMS_OUTPUT.PUT_LINE('Total: ' || total);
DBMS_OUTPUT.PUT_LINE('Average: ' || average);
DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;
The output throws an error saying how 'N' is not a procedure. I would appreciate some help in solving this issue.
There is a fundamental issue with your code, & is a substitution variable and is evaluated by the client application (i.e. SQL*Plus, SQL Developer or another client that supports substitution variables, which not all Oracle clients do) and is effectively implemented as if a find-replace was done on the source code.
Once the client has substituted the substitution variable then the statement is sent to the database where the PL/SQL engine will parse it. The PL/SQL engine never sees the substitution variable (because it is processed by the client application) and even if it did it would not understand how to handle it.
This means that you will be prompted for the replacement ONCE (and only once) and then that value will be used in every loop iteration so the loop will either never exit, if you enter a positive number first, or exit immediately, if you enter a negative number first.
If you want to enter a list of values then you need to enter them all at once:
SET SERVEROUTPUT ON;
DECLARE
items SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(0,1,2,3,4,5);
total NUMBER(3,0) := 0;
numZeros NUMBER(3,0) := 0;
average NUMBER(5,2) := NULL;
highest NUMBER(3,0) := NULL;
lowest NUMBER(3,0) := NULL;
BEGIN
FOR i IN 1 .. items.COUNT LOOP
total := total + items(i);
IF items(i) = 0 THEN
numZeros := numZeros + 1;
END IF;
IF highest IS NULL OR items(i) > highest THEN
highest := items(i);
END IF;
IF lowest IS NULL OR items(i) < lowest THEN
lowest := items(i);
END IF;
END LOOP;
IF items.COUNT > 0 THEN
average := total / items.COUNT;
END IF;
DBMS_OUTPUT.PUT_LINE('Total: ' || total);
DBMS_OUTPUT.PUT_LINE('Average: ' || average);
DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;
/
or, using SQL:
DECLARE
items SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(0,1,2,3,4,5);
total NUMBER(3,0) := 0;
numZeros NUMBER(3,0) := 0;
average NUMBER(5,2) := NULL;
highest NUMBER(3,0) := NULL;
lowest NUMBER(3,0) := NULL;
BEGIN
SELECT COALESCE(SUM(column_value),0),
COUNT(CASE column_value WHEN 0 THEN 1 END),
AVG(column_value),
MAX(column_value),
MIN(column_value)
INTO total,
numZeros,
average,
highest,
lowest
FROM TABLE(items);
DBMS_OUTPUT.PUT_LINE('Total: ' || total);
DBMS_OUTPUT.PUT_LINE('Average: ' || average);
DBMS_OUTPUT.PUT_LINE('Number of zeros: ' || numZeros);
DBMS_OUTPUT.PUT_LINE('Highest number: ' || highest);
DBMS_OUTPUT.PUT_LINE('Lowest number: ' || lowest);
END;
/
fiddle
If you want to take user input then you can replace the initial lines with:
SET SERVEROUTPUT ON;
ACCEPT number_list CHAR PROMPT 'Enter a comma-delimited list of numbers:'
DECLARE
items SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST(&&number_list);
Change this line:
n := &n;
Remove n;. It should be:
n := &
I don't know if you made a mistake with this line:
high := n;
It should be:
highest := n;
Same with this line:
low := n;
which should be:
lowest := n;
After that, when I run the code, I get this compilation error:
ORA-06502: PL/SQL: numeric or value error: number precision too large
This is because PL/SQL has no capabilities for getting input from the user during execution of PL/SQL code.
Indeed the & is a feature of SQL*Plus and not of PL/SQL.
The loop simply keeps repeating with the first entered value (for &) until total becomes larger than 999.
Refer to Taking user input 'n' times PL/SQL
and PL/SQL: how do I prompt user input in a procedure?
I have my bubble sorting algorithm which works correctly but I want to set it up so it prints each line in the process of the final output(19 lines).I have tried almost everything, but it doesn't print correctly:
program Bubble_Sort;
const N = 20;
var
d : array[1..N] of integer;
var
i,j,x : integer;
begin
randomize;
for i := 1 to N do d[i] := random(100);
writeln('Before sorting:'); writeln;
for i := 1 to N do write(d[i], ' ');
writeln;
for j := 1 to N - 1 do
for i := 1 to N - 1 do
write(d[i], ' ');
if d[i] > d[i+1] then
begin
x := d[i]; d[i] := d[i+1]; d[i+1] := x;
end;
writeln('After sorting:'); writeln;
for i := 1 to N do write(d[i], ' ');
writeln;
end.
The outer loop in the center of your code, the for j ... loop runs for each bubble iteration. That is where you want to output the state of the sorting. Because you thus have more than one statement within that for j ... loop, you must also add a begin .. end pair:
for j := 1 to N - 1 do
begin
//one round of sorting
//display result so far
end;
The sorting is ok as you have it, except when you added the write(d[i], ' '); presumably to output the sort result for one iteration, you changed the execution order to become totally wrong.
Remove the write(d[i], ' '); from where it is now.
To display the sorting result after each iteration add a new for k ... loop and a writeln;
for k := 1 to N do
write(d[k], ' ');
writeln;
Final sorting and progress display should be structured like:
for j := 1 to N - 1 do
begin
for i := 1 to N - 1 do
// one round of sorting
for k := 1 to N - 1 do
// output result of one sorting round
end;
DECLARE
m PLS_INTEGER := 0; n PLS_INTEGER := 0; k PLS_INTEGER;
BEGIN
<>
LOOP
n := n + 1; k := 0;
DBMS_OUTPUT.PUT_LINE ('The values of inner loop are: ');
<>
LOOP
k := k + 1;
m := m + n * k; -- Sum several products
EXIT inner_loop WHEN (k > 3);
DBMS_OUTPUT.PUT_LINE ('n='||TO_CHAR(n)||' k='||TO_CHAR(k)||' m='||TO_CHAR(m));
EXIT outer_loop WHEN ((n * k) > 6); END LOOP inner_loop;
END LOOP outer_loop;
DBMS_OUTPUT.PUT_LINE
('The total sum after completing the process is: ' || TO_CHAR(m));
END;
/
You wrongly labelled loops. Instead of just <> (which just means that something's different from something else), you should have used e.g. <<outer_loop>>. When fixed, your code looks like this:
SQL> set serveroutput on;
SQL> DECLARE
2 m PLS_INTEGER := 0;
3 n PLS_INTEGER := 0;
4 k PLS_INTEGER;
5 BEGIN
6 <<outer_loop>>
7 LOOP
8 n := n + 1; k := 0;
9 DBMS_OUTPUT.PUT_LINE ('The values of inner loop are: ');
10
11 <<inner_loop>>
12 LOOP
13 k := k + 1;
14 m := m + n * k; -- Sum several products
15
16 EXIT inner_loop WHEN (k > 3);
17 DBMS_OUTPUT.PUT_LINE ('n='||TO_CHAR(n)||' k='||TO_CHAR(k)||' m='||TO_CHAR(m));
18 EXIT outer_loop WHEN ((n * k) > 6);
19 END LOOP inner_loop;
20 END LOOP outer_loop;
21
22 DBMS_OUTPUT.PUT_LINE('The total sum after completing the process is: ' || TO_CHAR(m));
23 END;
24 /
The values of inner loop are:
n=1 k=1 m=1
n=1 k=2 m=3
n=1 k=3 m=6
The values of inner loop are:
n=2 k=1 m=12
n=2 k=2 m=16
n=2 k=3 m=22
The values of inner loop are:
n=3 k=1 m=33
n=3 k=2 m=39
n=3 k=3 m=48
The total sum after completing the process is: 48
PL/SQL procedure successfully completed.
SQL>
I've beeng having some trouble with this code... I need to create an algorithm which makes the user input a number (X), and then the program calculates the sum of all the odd numbers below (x).
This what I've tried so far, but can't really wrap my head around the logic behind it:
Program odd_numbers;
Var
Num, Limite, Soma: integer;
Begin;
Soma := 0;
Writeln('Choose a limit:');
Readln(Limite);
While (Limite / 2 > 0) do
Begin;
Soma := ((Num < Limite) mod 2 > 0);
Writeln('The sum of odd numbers from 0 to ', Limite, ' é ', Soma);
End;
if (Limite mod 2 = 0) then
Begin;
Soma := ((Num < Limite) mod 2 = 0);
Writeln('The sum of odd numbers from 0 to ', Limite, ' é ', Soma);
End;
End.
*PS: Been writing the code with variables in Portuguese, so don't mind the variables appearing weird to understand. *
I see that everyone is happily looping, but this is not necessary. This is a simple arithmetic sequence, and the sum can be calculated without a loop.
Just think of the following:
1 + 3 = 2 * (1 + 3) / 2 = 2 * 2 = 4 ; limits 3 and 4
1 + 3 + 5 = 3 * (1 + 5) / 2 = 3 * 3 = 9 ; limits 5 and 6
1 + 3 + 5 + 7 = 4 * (1 + 7) / 2 = 4 * 4 = 16 ; limits 7 and 8
1 + 3 + 5 + 7 + 9 = 5 * (1 + 9) / 2 = 5 * 5 = 25 ; limits 9 and 10
1 + 3 + 5 + 7 + 9 + 11 = 6 * (1 + 11) / 2 = 6 * 6 = 36 ; limits 11 and 12
But not only that, you'll see that it is in fact always a perfect square: Sqr((n+1) div 2).
So just calculate:
program odd_numbers;
var
Num, Limite, Soma: Integer;
begin
Write('Choose a limit: ');
Readln(Limite);
Num := (Limite + 1) div 2;
Soma := Num * Num;
Writeln('The sum of odd numbers from 0 to ', Limite, ' is ', Soma);
end.
Looks a little simpler than what the others propose.
The loop While (Limite / 2 > 0) do ... uses real arithmetic and not integer arithmetic. I guess you mean While (Limite div 2 > 0) do ... And you should change Limite in the loop otherwise you get stuck because the exit condition can never be reached.
After you have asked the user to enter a number, Limite, you need to keep that unchanged, because you need it in the final message. You also need a loop where you go through all numbers from Limite towards 0.
You started with a while loop which is ok, you are just missing the loop control variable. That is a variable that eventually gets a terminating value which then stops the loop. Use for example the Num variable you already have declared. You can use the same variable to investigate the numbers between user input and 0, for being odd values.
num := limite-1; // give num a start value based on user input (-1 because of "... numbers below (x)")
while num > 0 do // stop the loop when 0 is reached
begin
// here you investigate if `num` is a odd number (e.g. using `mod` operator or
// possibly your pascal has a built in `function Odd(value: integer): boolean;`)
// and add it to `Soma` if it is
num := num - 1;// decrement num at every iteration
end;
Finally you need to consider changes to the above, to handle negative input from the user.
To test if an integer is an odd value, you could use following function:
function IsOdd( value : Integer) : Boolean;
begin
IsOdd := (value mod 2) <> 0;
end;
Many pascal compilers have a built-in function called Odd(), which you could use.
A while loop works well to solve this problem. If you start with lowest odd number above zero, i.e. one and continue upwards so long we do not exceed the limit value we have a simple start:
function GetOddSumBelowX( X : Integer) : Integer;
var
i,sum: Integer;
begin
i := 1; // Start with first odd number
sum := 0;
while (i < X) do begin // as long as i less than X, loop
if IsOdd(i) then begin
sum := sum + i; // add to sum
end;
i := i + 1; // Increment i
end;
GetOddSumBelowX := sum;
end;
Now, that was simple enough. Next step to simplify the loop is to increment the i variable by two instead, just to jump between all odd numbers:
function GetOddSumBelowX( X : Integer) : Integer;
var
i,sum: Integer;
begin
i := 1; // Start with first odd number
sum := 0;
while (i < X) do begin // as long as i less than X, loop
sum := sum + i; // add to sum
i := i + 2; // Increment to next odd number
end;
GetOddSumBelowX := sum;
end;
DECLARE
i number(3);
j number(3);
BEGIN
i := 2;
LOOP
j:= 2;
LOOP
exit WHEN ((mod(i, j) = 0) or (j = i));
j := j +1;
END LOOP;
IF (j = i ) THEN
dbms_output.put_line(i || ' is prime');
END IF;
i := i + 1;
exit WHEN i = 50;
END LOOP;
END;
The code works properly. I tried to figure out how it works and ended up having 4 as a prime number, which isn't. If you could help me understand how this nested loop works, I'd be very thankful.
Thank you.
The code is looking for all the prime numbers up to 50. The outer loop is just checking each value of i from 2 to 50 to see if that integer is prime.
For each value of i, it tries to divide that integer by every other integer one by one, starting from 2. If i is divisible by j with no remainder (mod is zero) then it is not prime; unless it is only divisible by itself (j=1).
It exits that inner loop as soon as it finds a value of j which divides into i, or it reaches i itself.
It then needs a further check to see which of those conditions actually caused it to exit; and thus whether or not it is actually prime.
You could do the same thing with slightly clearer (IMHO) logic:
BEGIN
<<OUTER>>
FOR i IN 2..50 LOOP
FOR j IN 2..i-1 LOOP
IF (mod(i, j) = 0) THEN
CONTINUE OUTER;
END IF;
END LOOP;
dbms_output.put_line(i || ' is prime');
END LOOP;
END;
/
Lets rewrite it so its a bit simpler:
BEGIN
<<outer_loop>>
FOR value IN 2 .. 50 LOOP
FOR divisor IN 2 .. value - 1 LOOP
CONTINUE outer_loop WHEN MOD( value, divisor ) = 0;
END LOOP;
DBMS_OUTPUT.PUT_LINE( value || ' is prime' );
END LOOP;
END;
/
All it is doing is, in the outer loop going through the number 2 .. 50 and in the inner loop is checking whether there is a number that divides exactly into that value; if there is then continue the outer loop and if there is not then output that the number is prime.
Your code is effectively the same code but it is complicated by not using FOR .. IN .. loops
If I understand your question.
When i = 4 and j = 2 then condition ((mod(i, j) = 0) or (j = i)) leads to the exit from inner loop, but condition (j = i ) is false and program doesn't go to line dbms_output.put_line(i || ' is prime');