postgresql中Exponential的存储过程

时间:2012-08-30 06:07:26

标签: postgresql stored-procedures exponential postgresql-9.0

在PostgreSQL中我收到错误:

ERROR: argument for function "exp" too big
SQL state: 22003

我需要为指数编写一个存储过程:

  • 如果exp(value)抛出函数“exp”太大的参数
  • 然后返回0
  • else return exp(value)

请帮我解决如何处理此存储过程的问题。

1 个答案:

答案 0 :(得分:2)

这就是发生的事情:

regress=# SELECT exp(NUMERIC '6000');
ERROR:  argument for function "exp" too big

您将一个不切实际的大值传递给exp()。它太大而不能溢出float8(双倍)并且只能表示为NUMERIC。即使在那里,也有一个限制,当你超过exp(5999)时,你会点击它。

对于硬数学,您可能需要尝试PL/R,即R语言的数据库内嵌式版本。

很难说该怎么做,因为你还没有真正解释查询的内容,exp的输入应该是什么等等。

对于太大的指数而言,归零是有点疯狂。为什么呢?


要捕获异常,请在PL / PgSQL中使用BEGIN ... EXCEPTION

我写了下面的函数来返回NaN(“不是数字”)而不是零,因为我认为返回零只是完全错误。如果需要,可以更改它。返回NULL可能也有点意义。

CREATE OR REPLACE FUNCTION exp_if_possible(numeric) RETURNS numeric as $$
BEGIN
    RETURN exp($1);
EXCEPTION
    WHEN numeric_value_out_of_range THEN
        RETURN 'NaN';
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE;

错误代码numeric_value_out_of_range是通过在Pg手册中查找Appendix A. PostgreSQL Error CodesSQLSTATE 22003范围内的exp获得的BEGIN ... EXCEPTION获得的。您会在有关exp(6000)的文档中看到指向该链接的链接。


我最初说如果要完成它应该通过测试输入来完成,但我认为我错了。无法保证限制为CREATE OR REPLACE FUNCTION crazy_exp(numeric) RETURNS numeric AS $$ -- exp(6000) and above will throw 'argument for function "Exp" too big -- For such cases, return zero because [insert explanation here] SELECT CASE WHEN $1 < 6000 THEN exp($1) ELSE 0 END; $$ LANGUAGE 'sql' IMMUTABLE; CREATE OR REPLACE FUNCTION crazy_exp(float8) RETURNS float8 AS $$ -- float8 goes out-of-range above about exp(600) SELECT CASE WHEN $1 <= 600 THEN exp($1) ELSE 0 END; $$ LANGUAGE 'sql' IMMUTABLE; ,因此您使用异常处理是正确的,即使它很慢也很笨拙。我将在一秒内用异常处理版本更新此响应。

{{1}}

比在PL / PgSQL中捕获“超出范围”异常更有效率,并使你的意图更清晰。