我意识到这是一篇旧的(非常旧的)帖子,但我最近看到了几个关于浮点值的问题。因此,当我遇到这个问题时,我挖掘了一个用于进行浮点比较的旧例程。希望这对未来的搜索者有用。顺便说一句,它不需要转换为字符串,因为它比较相对值。
create or replace function compare_float(
float_value_1 double precision
, float_value_2 double precision
, delta_value double precision default 1.0e-6
)
return integer
is
/*
Name: Compare_Float
Author: Belayer
Date Written: 22-Jan-2009
Floating point number are ALWAYS estimates as there is no way to precisely a
decimal base 10 number in binary. Therefore comparing 2 floating points of
for equality is a risky proposition at best.
While the above is true, we can at least inquire as to the difference being
enough as to not matter and then consider the values as equal even though
in the computed since they may not be.
This routine implements the 'close enough' comparison to give the relative
magnitude relationship between 2 floating point variables.
Parameters:
Float_Value_1. The first of 2 floating point values to be compared.
Float_Value_2. The second of he 2 floating point values to be compared.
Delta_Value. The amount of the 2 values can differ and still be considered
to be equal. Default value 10^-6 (.000001) This value can be
overridden on each call to the procedure.
Return Values:
-1 Float_Value_1 is less than Float_Value_2.
0 Float_Value_1 equals Float_Value_2 within specified Datla_Value.
1 Float_Value_1 is greater than Float_Value_2.
*/
delta_diff double precision;
compare_float_result integer;
begin
delta_diff := float_value_1 - float_value_2;
if abs(delta_diff) < delta_value
then
compare_float_result := 0;
else
compare_float_result := sign(delta_diff);
end if;
return compare_float_result;
end compare_float;
以下测试使用为 delta_value 指定的不同值的相同值,允许的值之间的差异仍然被认为是相等的。使用值 1.0e-6(默认)、1.0e-3 和 1.0e-7 进行测试。
-- test 1.3e-6 (default)
with vals (f,s,e) as
( select 10.12432, 10.124, 1 from dual union all
select 10.124, 10.124001, -1 from dual union all
select 1.0000124, 1.0000120, 0 from dual union all
select 1.000124, 1.000120, 1 from dual union all
select 1.11000015, 1.12000015,-1 from dual union all
select 0.0000010, 0.00000011, 0 from dual
)
select compare_float(f,s) result, e expecting
from vals;
-- test 1.3e-3 (default)
with vals (f,s,e) as
( select 10.12432, 10.124, 0 from dual union all
select 10.124, 10.124001, 0 from dual union all
select 1.0000124, 1.0000120, 0 from dual union all
select 1.000124, 1.000120, 0 from dual union all
select 1.11000015, 1.12000015,-1 from dual union all
select 0.0000010, 0.00000011, 0 from dual
)
select compare_float(f,s, 1.0e-3) result, e expecting
from vals; '
-- test 1.3e-7
with vals (f,s,e) as
( select 10.12432, 10.124, 1 from dual union all
select 10.124, 10.124001, -1 from dual union all
select 1.0000124, 1.0000120, 1 from dual union all
select 1.000124, 1.000120, 1 from dual union all
select 1.11000015, 1.12000015,-1 from dual union all
select 0.0000010, 0.00000011,-1 from dual
)
select compare_float(f,s, 1.0e-7) result, e expecting
from vals;
好吧,有人想要它。注意:这个例程来自一个更老的 Fortran。