powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Арифметические операции с типом BINARY_DOUBLE
8 сообщений из 8, страница 1 из 1
Арифметические операции с типом BINARY_DOUBLE
    #39674645
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

Кто-нибудь может мне объяснить что происходит?

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
DECLARE 
  double_N   BINARY_DOUBLE := 5000000;
  double_pi  BINARY_DOUBLE := 3.1415926536;
  double_S   BINARY_DOUBLE := 0.0;
  i          BINARY_DOUBLE := 1.0;
  start_time PLS_INTEGER   := 0;
  end_time   PLS_INTEGER   := 0;
BEGIN
  start_time := dbms_utility.get_time;  
  
/*  FOR i IN 1..double_N
  LOOP
    double_S := double_PI * (i * i);
  END LOOP;*/
  
  LOOP
    double_S := double_PI * (i * i);
    i := i + 1;
    EXIT WHEN i > 5000000;
  END LOOP;
  
  end_time := dbms_utility.get_time; 
  
  dbms_output.put_line(end_time - start_time);
end;



Почему первый цикл вылетает с ошибкой, а второй цикл успешно выполняется?
Я смутно представляю, что индекс цикла for неявно преобразуется до целочисленного типа.
Но как в итоге считается финальное double_S, что оно выходит за рамка, не понимаю.
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674656
merch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNO,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
declare 
  double_n   binary_double := 5000000;
  double_pi  binary_double := 3.1415926536;
  double_s   binary_double := 0.0;
  i          binary_double := 1.0;
  start_time pls_integer   := 0;
  end_time   pls_integer   := 0;
Begin
  start_time := dbms_utility.get_time;  
  
  for i in 1..double_n
  loop
    double_s := double_pi * i * i;
  end loop;
   
  end_time := dbms_utility.get_time; 
  dbms_output.put_line(end_time - start_time);
e

nd;
/
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674657
merch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
merch,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
declare 
  double_n   binary_double := 5000000;
  double_pi  binary_double := 3.1415926536;
  double_s   binary_double := 0.0;
  i          binary_double := 1.0;
  start_time pls_integer   := 0;
  end_time   pls_integer   := 0;
Begin
  start_time := dbms_utility.get_time;  
  
  for i in 1..double_n
  loop
    double_s := double_pi * i * i;
  end loop;
   
  end_time := dbms_utility.get_time; 
  dbms_output.put_line(end_time - start_time);
end;
/
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674667
merch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или так:

Код: plsql
1.
double_pi * (to_binary_double(i) * i)
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674685
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNOиндекс цикла for неявно преобразуетсяНе преобразуется. Это другая переменная.
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674890
IMNO
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так это скобки мешали? Как так-то?

Насколько я понимаю тип binary_double перемножает числа как мантисса и порядок.
То есть например:
Код: plsql
1.
double_s := 12E14 * 10000000 * 10000000;


Так код отработает, потому что в переменной будет увеличиваться только порядок, в результате чего разрядность числа будет такая, что оно влезет в тип binary_double.

Но например так:
Код: plsql
1.
double_s := 12E14 * (10000000 * 10000000);



Число неявно преобразуется до вида без порядка, что в итоге даёт разрядность, которая не влазит в binary_double. Отсюда и ошибка переполнения.
Всё верно, или я в чём-то неправ?

Я ещё нашёл вот такую штуку.
Так работает:
Код: plsql
1.
2.
double_N := double_pi * 5000000 * 5000000;
dbms_output.put_line(double_N);



Так не работает:
Код: plsql
1.
2.
double_N := 5000000 * 5000000 * double_pi ;
dbms_output.put_line(double_N);
...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674903
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
IMNOВсё верно, или я в чём-то неправ?При plsql_optimize_level>0 выражения с целочисленными константами предвычисляются в константу с типом PLS_INTEGER. Это фича.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SQL> exec dbms_output.put_line(5000000*5000000)
BEGIN dbms_output.put_line(5000000*5000000); END;

*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 1


SQL> exec dbms_output.put_line(5000000.*5000000)
25000000000000

PL/SQL procedure successfully completed.

...
Рейтинг: 0 / 0
Арифметические операции с типом BINARY_DOUBLE
    #39674922
merch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic, я на 11.2.0.4.0 вчера на уровне сессии пробовал plsql_optimize_level выставлять в 0, не помогло.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Арифметические операции с типом BINARY_DOUBLE
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]