забавный баг с binary_double

_Nikotin
Дата: 19.11.2009 20:21:04
Совершенно случайно наткнулись на баг оракла:

with t as
(
  select cast(9960 as binary_float) a from dual
  union all
  select cast(9962 as binary_float) from dual  
)
select stddev(a) from t

например на этих данных выдаёт 0
_Nikotin
Дата: 19.11.2009 20:23:49
повторяется на

Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
PL/SQL Release 10.2.0.4.0 - Production
CORE	10.2.0.4.0	Production
TNS for Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production

Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - Production
PL/SQL Release 11.1.0.7.0 - Production
CORE	11.1.0.7.0	Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production
-2-
Дата: 19.11.2009 21:00:12
_Nikotin,

С binary_double как раз похоже на правду. Косячит округление более короткого binary_float.
Попробовал дописать ко второму числу дробную часть (float):
9962.00.0
9962.10.0
9962.25.3985386
9962.30.0
9962.42.3103707
Sergei.Agalakov
Дата: 19.11.2009 21:08:11
Declare
  pi number := 3.1415926535897932384626433832795;
  l_res number;
Begin
--   z = tan(pi/2.0);
 select tan(pi/2.0) into l_res from dual;
dbms_output.put_line('Number: '||l_res);
 select tan(cast(pi as binary_float)/2.0) into l_res from dual;
dbms_output.put_line('Float: '||l_res);
 select tan(cast(pi as binary_double)/2.0) into l_res from dual;
dbms_output.put_line('Double: '||l_res);
End;  

Number: 693428379249849179327513157803496.265883
Float: -22877332.428855401
Double: 16331778728383844

Floating point precision
_Nikotin
Дата: 19.11.2009 23:29:25
-2-,

дробная-не дробная, значения не имеет, деление/умножение на 2 на результат не влияет, то есть значение зависит только от мантиссы. пар чисел довольно много, зависимости в двоичном представлении не увидел.

зато NAN и INF поддерживаются
mayton
Дата: 19.11.2009 23:33:44
_Nikotin
Совершенно случайно наткнулись на баг оракла


С binary_double вроде всё нормально.

Oracle11g:
SQL> with t as
  2  (
  3    select 9960d a from dual
  4    union all
  5    select 9962d from dual
  6  )
  7  select stddev(a) from t;

 STDDEV(A)
----------
1.414E+000

C float - действительно баг. Хотя среднее значение считает верно.

SQL> with t as
  2  (
  3    select 9960f a from dual
  4    union all
  5    select 9962f from dual
  6  )
  7  select stddev(a) from t;

 STDDEV(A)
----------
         0

SQL> with t as
  2  (
  3    select 9960f a from dual
  4    union all
  5    select 9962f from dual
  6  )
  7  select avg(a) from t;

    AVG(A)
----------
9.961E+003
_Nikotin
Дата: 19.11.2009 23:41:17
mayton,

с avg тоже были ошибки, точно завтра могу сказать на какой паре чисел.
для двух это отчетливо видно, а сколько кривых результатов уже сидит в базе - грустно подумать, заказчики пока не заметили, но думаю что придут в ужас.
mayton
Дата: 19.11.2009 23:57:15
Можно попробовать сделать перерасчёт в NUMBER, если экспонента была не слишком велика.
Sergei.Agalakov
Дата: 20.11.2009 01:25:20
select 9962f* 9962f as a1f,
       9962 * 9962  as a1n,
       9963f* 9963f as a2f,
       9963 * 9963  as a2n
  from dual
Не могу с ходу найти ссылки, но для float можно доверять 7 значащим цифрам, а для double 15. Даже при этом иногда поджидают сюрпризы типа моего примера с tan(pi/2).
mayton
Дата: 20.11.2009 09:30:24
Кто-нибудь "отстучал" на металинк?