これが古い (非常に古い) 投稿であることは承知していますが、最近、浮動小数点値に関するいくつかの質問を見てきました。そこで、これに出くわしたとき、浮動小数点比較を行うために持っていた古いルーチンを掘り起こしました。これが将来の検索者に役立つことを願っています。ところで、相対値を比較するため、文字列への変換は必要ありません。
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 をソースとしています。