在 PostgreSQL 中发生下溢错误时是否有解决方法?
Is there a workaround when an underflow error occurs in PostgreSQL?
我有一个 table 在每一行中包含以下公式中指数曲线的 a、b 和 c 参数:
a*exp(-b*x)+c
所有列都是双精度类型。
我希望以特定的 x 值对每条曲线进行采样,并将其值记录在新列中。但是,这样做会导致下溢错误。
>update curve_by_wkt set samplepoint05 = a*exp(-b*0.05)+c;
ERROR: value out of range: underflow
我无法手动检查 a、b、c 的哪些值导致计算失败。我所知道的是不需要极高的精度,并且特定范围之外的值可能无关紧要。
考虑到我对精度的漠视,我想知道是否有任何方法可以完成计算。
谢谢
创建函数并捕获异常。您可以提出自己的错误信息:
create or replace function calculate_with_error
(a double precision, b double precision, c double precision, x double precision)
returns double precision language plpgsql as $$
begin
return a * exp(-b * x) + c;
exception when numeric_value_out_of_range then
raise exception 'Value out of range for a = % b= % c= % x= %', a, b, c, x;
end $$;
select calculate_with_error(1, 1, 0, 10000);
ERROR: Value out of range for a = 1 b= 1 c= 0 x= 10000
或设置一些默认值:
create or replace function calculate_with_default
(a double precision, b double precision, c double precision, x double precision)
returns double precision language plpgsql as $$
begin
return a * exp(-b * x) + c;
exception when numeric_value_out_of_range then
return 0;
end $$;
select calculate_with_default(1, 1, 0, 10000);
calculate_with_default
------------------------
0
(1 row)
用法:
update curve_by_wkt
set samplepoint05 = calculate_with_error(a, b, c, 0.05);
更好的解决方案(最有可能)是仅使用 greatest
函数设置最小值。例如,
greatest(a*exp(-b*x)+c, -50)
大多数时候 0 或某个任意低的数字就足够了。
我有一个 table 在每一行中包含以下公式中指数曲线的 a、b 和 c 参数:
a*exp(-b*x)+c
所有列都是双精度类型。 我希望以特定的 x 值对每条曲线进行采样,并将其值记录在新列中。但是,这样做会导致下溢错误。
>update curve_by_wkt set samplepoint05 = a*exp(-b*0.05)+c;
ERROR: value out of range: underflow
我无法手动检查 a、b、c 的哪些值导致计算失败。我所知道的是不需要极高的精度,并且特定范围之外的值可能无关紧要。
考虑到我对精度的漠视,我想知道是否有任何方法可以完成计算。
谢谢
创建函数并捕获异常。您可以提出自己的错误信息:
create or replace function calculate_with_error
(a double precision, b double precision, c double precision, x double precision)
returns double precision language plpgsql as $$
begin
return a * exp(-b * x) + c;
exception when numeric_value_out_of_range then
raise exception 'Value out of range for a = % b= % c= % x= %', a, b, c, x;
end $$;
select calculate_with_error(1, 1, 0, 10000);
ERROR: Value out of range for a = 1 b= 1 c= 0 x= 10000
或设置一些默认值:
create or replace function calculate_with_default
(a double precision, b double precision, c double precision, x double precision)
returns double precision language plpgsql as $$
begin
return a * exp(-b * x) + c;
exception when numeric_value_out_of_range then
return 0;
end $$;
select calculate_with_default(1, 1, 0, 10000);
calculate_with_default
------------------------
0
(1 row)
用法:
update curve_by_wkt
set samplepoint05 = calculate_with_error(a, b, c, 0.05);
更好的解决方案(最有可能)是仅使用 greatest
函数设置最小值。例如,
greatest(a*exp(-b*x)+c, -50)
大多数时候 0 或某个任意低的数字就足够了。