Click to See Complete Forum and Search --> : How to get ride of ORA-01426: numeric overflow error?


Kumar_RP
11-21-2005, 01:45 PM
Hi,
I am tring to create this function for factorial calculation.

CREATE OR REPLACE FUNCTION fac (n POSITIVE) RETURN INTEGER IS
BEGIN
IF n = 0 THEN
RETURN 1;
ELSIF n = 1 THEN
RETURN 1;
ELSE
RETURN n * fac(n - 1);
END IF;
END fac;


When i am executing this function as

select FAC(34) from dual
*
ERROR at line 1:
ORA-01426: numeric overflow

ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: number precision too large

Can someone help me about the problem with this function.

Thanks
Regards,
Kumar

Scorby
11-21-2005, 02:11 PM
You've probably gone beyond the limit Oracle can cope with for a number variable. I think it can only go up to number(39).

tamilselvan
11-21-2005, 03:14 PM
CREATE OR REPLACE FUNCTION fac (n POSITIVE) RETURN INTEGER

Change the NUMBER to FLOAT.

CREATE OR REPLACE FUNCTION fac (n POSITIVE) RETURN FLOAT

SQL> select fac(34) from dual ;

FAC(34)
----------
2.9523E+38


Tamil

Kumar_RP
11-21-2005, 03:46 PM
Thanks for your reply Tamil..
But i have one more question for you :).

select FAC(83) from dual;
FAC(83)
----------
3.946E+124

select FAC(84) from dual;
FAC(84)
---------
~

Is there any other work around to resolve this.. I need to calculate till FAC(100) :).

Thanks in Advance
Regards,
Kumar

tamilselvan
11-21-2005, 04:23 PM
Thanks for your reply Tamil..
But i have one more question for you :).

select FAC(83) from dual;
FAC(83)
----------
3.946E+124

select FAC(84) from dual;
FAC(84)
---------
~

Is there any other work around to resolve this.. I need to calculate till FAC(100) :).

Thanks in Advance
Regards,
Kumar

You need to use IBM Mainframe and FORTRAN to calculate FAC(100).

Tamil

gandolf989
11-21-2005, 05:08 PM
You need to use IBM Mainframe and FORTRAN to calculate FAC(100).

Tamil

For example.


CREATE OR REPLACE FUNCTION fac ( n NUMBER )
RETURN NUMBER
IS
BEGIN
IF n = 0
THEN
RETURN 1;
ELSIF n = 1
THEN
RETURN 1;
ELSE
RETURN n * fac ( n - 1 );
END IF;
END fac;
/

SELECT TO_CHAR(fac( 9), '999,999,999') factor_9,
TO_CHAR(fac(10), '999,999,999') factor_10,
TO_CHAR(fac(10) - fac(9),
'999,999,999') factor_diff,
TO_CHAR(fac(30), '999,999,999,999,999,999,999,999,999,999,999') factor_30
FROM dual;

FACTOR_9 FACTOR_10 FACTOR_DIFF FACTOR_30
------------ ------------ ------------ --------------------------------------------
362,880 3,628,800 3,265,920 265,252,859,812,191,058,636,308,480,000,000


You can see that the result grows exponentially. Is this a homework assignment??? :rolleyes:

slimdave
11-21-2005, 05:32 PM
cheating only slightly ...
CREATE OR REPLACE FUNCTION fac (n POSITIVE) RETURN varchar2 IS
BEGIN
IF n = 0 THEN
RETURN 1;
ELSIF n = 1 THEN
RETURN 1;
ELSIF n = 100 THEN
RETURN '933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182 86253697920827223758251185210916864000000000000000000000000';
ELSE
RETURN n * fac(n - 1);
END IF;
END fac;

gandolf989
11-21-2005, 05:39 PM
cheating only slightly ...
CREATE OR REPLACE FUNCTION fac (n POSITIVE) RETURN varchar2 IS
BEGIN
IF n = 0 THEN
RETURN 1;
ELSIF n = 1 THEN
RETURN 1;
ELSIF n = 100 THEN
RETURN '933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182 86253697920827223758251185210916864000000000000000000000000';
ELSE
RETURN n * fac(n - 1);
END IF;
END fac;


Perhaps you can create a case function to deal with all of the numbers between 30 and 100. :D


CCDOTTSVR@vizdev> select fac(99) from dual;
select fac(99) from dual
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10
ORA-06512: at "CCDOTTSVR.FAC", line 10

slimdave
11-21-2005, 06:02 PM
Tsh. Fussy fussy. Just calculate it somewhere else and use a lookup table. Be faster ;)

Kumar_RP
11-23-2005, 01:01 PM
Hi Folks,
Thanks for your responses about my doubt..

Slimdave... can you please give some more clear idea about whats the need of putting N = 100 as default value.?..

Tamil.. Can you please throw some lights on your answer " Use IBM or FORTRAN "??

Thanks in advance.

Happy Thanks Giving!!!

Regards,
Kumar

tamilselvan
11-23-2005, 01:35 PM
Hi Folks,
Thanks for your responses about my doubt..

Slimdave... can you please give some more clear idea about whats the need of putting N = 100 as default value.?..

Tamil.. Can you please throw some lights on your answer " Use IBM or FORTRAN "??

Thanks in advance.

Happy Thanks Giving!!!

Regards,
Kumar

If you can access IBM supercomputer and then use FORTRAN language or C language, to calculate all FAC values, and then use the results in Oracle's function. The function will return varchar2 instead of float.
Oracle RDBMS is not designed for Scientific calculation.

Tamil

slimdave
11-23-2005, 02:21 PM
Slimdave... can you please give some more clear idea about whats the need of putting N = 100 as default value.?..

I was cheating by using a precalculated value. Note that I changed the return type of the function to varchar2 also.