Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
А почему интересно
SQL> select to_char(cast(cast(1 + 1/power(2,52) as binary_double) as number), 'TM9') from dual;

TO_CHAR(CAST(CAST(1+1/POWER(2,52)ASBINARY_DOUBLE)ASNUMBER),'TM9'
----------------------------------------------------------------
1.0000000000000002


а не

SQL> select to_char(1 + 1/power(2,52), 'TM9') from dual;

TO_CHAR(1+1/POWER(2,52),'TM9')
----------------------------------------------------------------
1.00000000000000022204460492503130808473


?

То есть почему так сделали можно понять, а вот явлеется ли это багом?
26 дек 11, 00:10    [11823413]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 51758

У double чисто технически точность 15 знаков. Больше из него не выжать.

Posted via ActualForum NNTP Server 1.5

26 дек 11, 00:21    [11823425]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
А возникает ли вопрос, если заменить to_char dump-ом?
26 дек 11, 00:23    [11823431]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
Для меня ответ на вопрос что к чему приводить неявно очевиден даже без заглядывания в документацию.
Мало того, что попсовый binary_double недостаточно точен, он недостаточно предсказуемо точен.

P.S. Спрашивается а куя на вообще его внедрили? :)
26 дек 11, 00:27    [11823440]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Dimitry Sibiryakov,

Во-первых не выжать больше 15 наперед заданных десятичных знаков. Во-вторых double представляет собой разложение по степеням двойки. И 1.0000000000000002 хранится в double как 1 + 2 ^ (-52) что вообще 1.00000000000000022204460492503130808473..., а не то что получилось по факту.
26 дек 11, 00:28    [11823442]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Elic
P.S. Спрашивается а куя на вообще его внедрили? :)


Для хранения результатов научных расчётов без искажения, связанного с преобразованием дробей по основанию 10 в дроби по основанию 2.
26 дек 11, 00:44    [11823493]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
mcureenab
Для хранения результатов научных расчётов без искажения, связанного с преобразованием дробей по основанию 10 в дроби по основанию 2.
А зачем преобразовывать более точное в менее точное?
26 дек 11, 00:53    [11823511]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Для чего полезен вроде как очевидно - для математики:

SQL> set timing on
SQL> select sum(ln(1d+level)) from dual connect by level <= 1e6;

SUM(LN(1D+LEVEL))
-----------------
       1.282E+007

Elapsed: 00:00:01.39
SQL> select sum(ln(1+level)) from dual connect by level <= 1e6;

SUM(LN(1+LEVEL))
----------------
      12815532.2

Elapsed: 00:00:18.81
26 дек 11, 01:03    [11823525]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
_Nikotin
Для чего полезен вроде как очевидно - для математики:
Привет институту ядерных исследований. Они до 10g не успевали исследовать :)

P.S. Быстро, но неточно - попса, чистой воды :)
26 дек 11, 01:08    [11823536]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Elic
mcureenab
Для хранения результатов научных расчётов без искажения, связанного с преобразованием дробей по основанию 10 в дроби по основанию 2.
А зачем преобразовывать более точное в менее точное?


_Nikotin_нарисовал пример преобразования. Дело даже не в точности, а в том что из-за преобразования получаются бесконечные дроби. Их невозможно сохранить в NUMBER без потери точности. И обратное преобразование придётся делать с оглядкой на количество точных цифр.
26 дек 11, 01:11    [11823547]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Elic
Привет институту ядерных исследований. Они до 10g не успевали исследовать :)

Зачем же сразу ядерные исследования, есть же фармацевты :)
26 дек 11, 01:15    [11823555]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
mcureenab
а в том что из-за преобразования
Исходные данные не следует преобразовывать из форматов, в которых их вводили. Дабы не появлялись куреенабовские измышлизЪмы.
26 дек 11, 01:17    [11823561]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Elic
Member

Откуда:
Сообщений: 29976
_Nikotin
Зачем же сразу ядерные исследования, есть же фармацевты :)
Мы о скорости? Как фармацевт фармацевту скажу, что "нам" скорость расчётов монопенисуальна :) Да что "нам" там рассчитывать-то?
26 дек 11, 01:20    [11823568]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Elic
Для меня ответ на вопрос что к чему приводить неявно очевиден даже без заглядывания в документацию.
Мало того, что попсовый binary_double недостаточно точен, он недостаточно предсказуемо точен.

P.S. Спрашивается а куя на вообще его внедрили? :)
Мне вот тоже непонятно.
Особенно понравилось, что потеря точности появляется даже при работе с целыми числами.
Например, подсчитаем сумму арифметической прогрессии от 1 до 228-1.
declare
  n binary_double := 0;
begin
  for i in 1 .. power(2, 28) - 1 loop
    n := n + i;
  end loop;
  dbms_output.put_line(to_char(n, '00000000000000000000'));
end;
/
00036028796817637376

PL/SQL procedure successfully completed.

Elapsed: 00:00:19.46

declare
  n number := 0;
begin
  for i in 1 .. power(2, 28) - 1 loop
    n := n + i;
  end loop;
  dbms_output.put_line(to_char(n, '00000000000000000000'));
end;
/
00036028796884746240

PL/SQL procedure successfully completed.

Elapsed: 00:00:34.24

select to_char(((power(2,28))-1)*(power(2,28))/2,'00000000000000000000') value from dual;

VALUE
---------------------
 00036028796884746240

Elapsed: 00:00:00.01
Ну выполняется чуток быстрее. Только что толку, если результат неправильный?
26 дек 11, 04:48    [11823723]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
Вячеслав Любомудров
Member

Откуда: Владивосток
Сообщений: 18482
-- Моя программа выполняется в 5 раз быстрее!
-- Зато моя правильно

Мне кажется, надо просто знать особенности и применять по назначению (врача)
Это может быть не очень доступно тем, кто не занимался программированием, когда это было критично. Сейчас большинство может этим пренебречь
26 дек 11, 05:03    [11823731]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
Elic
mcureenab
а в том что из-за преобразования
Исходные данные не следует преобразовывать из форматов, в которых их вводили. Дабы не появлялись куреенабовские измышлизЪмы.


Твои слова Богу в уши.
1. Кто сказал, что данные всегда заводятся в виде десятичных чисел?
2. Та же интеграция с Java потребует преобразований чисел в нативный формат.
3. Сложные вычисления проводить на оракловой арифметике вообще никому в голову не придёт.


  1  declare
  2    n number := 0;
  3    m binary_double := 0;
  4    j pls_integer;
  5  begin
  6    for i in 1 .. 134217730 loop
  7      n := n + i;
  8  --    m := m + i;
  9  --    exit when n != m;
 10    end loop;
 11    dbms_output.put_line(to_char(n, '00000000000000000000'));
 12    dbms_output.put_line(to_char(m, '00000000000000000000'));
 13* end;
SQL> /
00009007199590285315
00000000000000000000

PL/SQL procedure successfully completed.

Elapsed: 00:01:43.32
SQL> edi
Wrote file afiedt.buf

  1  declare
  2    n number := 0;
  3    m binary_double := 0;
  4    j pls_integer;
  5  begin
  6    for i in 1 .. 134217730 loop
  7  --    n := n + i;
  8      m := m + i;
  9  --    exit when n != m;
 10    end loop;
 11    dbms_output.put_line(to_char(n, '00000000000000000000'));
 12    dbms_output.put_line(to_char(m, '00000000000000000000'));
 13* end;
SQL> /
00000000000000000000
00009007199590285314

PL/SQL procedure successfully completed.

Elapsed: 00:00:38.71
SQL> 
26 дек 11, 10:19    [11824415]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Кобанчег
Особенно понравилось, что потеря точности появляется даже при работе с целыми числами.

Потеря и у number-а будет, только несколько позже.
Вот ещё один старый пример 7953266, в заголовке только надо binary_float поставить. С double проблема на более больших числах возникает, с number на ещё более больших.
26 дек 11, 11:30    [11824990]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
mcureenab
Member

Откуда: Murmansk
Сообщений: 5928
_Nikotin
Кобанчег
Особенно понравилось, что потеря точности появляется даже при работе с целыми числами.

Потеря и у number-а будет, только несколько позже.


У NUMBER хорошо видно потерю точности целого числа, когда младшие разряды становятся равны 0 и инкремент на 1 не меняет число.

За счёт преобразования BINARY_DOUBLE в NUMBER образуется хвост из степеней 2, который затрудняет выделение точных разрядов десятичного числа.

И в самом деле, 1024 не оканчивается на 0, хотя может храниться в однобитной мантиссе с 4х битным порядком (без знака). Число может содержать лишь 1 бит точных двоичных разрядов и ни одного точного десятичного разряда.

В примере _Nikotun_ была значительно превышена разрядность BINARY_DOUBLE. При таких обстоятельствах результат будет зависеть даже от порядка сложения ряда (правило - нельзя суммировать малые и большие числа).
26 дек 11, 13:58    [11826424]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
Ещё один плюс у binary_double - больше экспонения, что позволяет хранить числа в диапазоне 2.22507485850720E-308 ... 1.79769313486231E+308. Также он позволяет оперировать с сабнормальными числами (у number-а их нет - за наименьшим с полной мантиссой идёт сразу 0):
SQL> select dump(4e-324d) from dual;
 
DUMP(4E-324D)
--------------------------------
Typ=101 Len=8: 128,0,0,0,0,0,0,1
26 дек 11, 14:54    [11826981]     Ответить | Цитировать Сообщить модератору
 Re: binary_double и number  [new]
_Nikotin
Member

Откуда: СПб
Сообщений: 2965
_Nikotin
Ещё один плюс у binary_double - больше экспонента, что позволяет ....
26 дек 11, 15:01    [11827070]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить