在PostgreSQL中我收到错误:
ERROR: argument for function "exp" too big
SQL state: 22003
我需要为指数编写一个存储过程:
exp(value)
抛出函数“exp”太大的参数exp(value)
请帮我解决如何处理此存储过程的问题。
答案 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 Codes中SQLSTATE 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中捕获“超出范围”异常更有效率,并使你的意图更清晰。