Search code examples
postgresqlplpgsqlpgadminfactorial

"bigint out of range" when computing factorial function in PostgresSQL


As part of an intro to databases class, we've been told to create a function using PL/pgSQL that gives out a factorial of a number. Now since x! increases rapidly as a function, we've decided to return a bigint due to it being a large range integer.

CREATE OR REPLACE FUNCTION getBigFactorial(fn bigint) RETURNS bigint as $$
DECLARE
 product bigint;
 minus1 int;
BEGIN
 if (fn > 21) then
 RAISE EXCEPTION 'Error: computing factorial; numeric value out of range';
 return NULL;
 elsif (fn < 1) then
 RAISE EXCEPTION 'Error: Argument less than 1!';
 return NULL;
 end if;
 
 minus1 := fn - 1;
 if (minus1 > 0) then
 product := fn * getBigFactorial(minus1);
 return product;
 end if;
 return fn;
END;
$$ language plpgsql;

For this function, we've been told to create some sort of validation for the number entered. The one for (fn < 1) worked flawlessly, however, the one which is (fn > 21) is giving some problems.

When the following is entered:

SELECT getBigFactorial(21);

We get:

ERROR:  bigint out of range
CONTEXT:  PL/pgSQL function getbigfactorial(integer) line 17 at assignment
SQL state: 22003

rather than getting the desired output. Line 17 corresponds to this line:

 if (minus1 > 0) then

When we entered 22 instead of 21, we had the desired error output.

Any help in finding out what causes this? TIA


Solution

  • Your conditional check should be inclusive of 21:

    if (fn >= 21) then
    -- ...
    

    since for an input of 21, the factorial of 21 (fn * getBigFactorial(minus1), where fn = 21, and minus1 = fn - 1), which is an integer out of range for a bigint, is assigned to product, a bigint.