Деление больших чисел (все глючнее и глючнее)

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Деление больших чисел (все глючнее и глючнее)

Сообщение Володя Т. » 29 янв 2007, 19:04

Судя по всему умножение больших чисел FB исправлять пока не собирается. Проблема там понятная.
Но вот сегодня наткнулся на проблему деления. Откуда она берётся пока не понял:

create procedure test returns (c numeric(18,7))
as
declare variable A numeric(18,7);
declare variable B numeric(18,7);
begin
A = 100000000;
B = 1000;
C = A / B;
end

не делит. "ошибка" - говорит FB 1.5 в диалекте 3
Разработчики! Когда исправите?
Или в FB 2.0 поправлено уже?
Хваля IB платформу я обычно умалчиваю о таких глюках, но Стыдно! Уйду от вас в нелюбимый MSSQL - будете знать :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 29 янв 2007, 21:59

делим 18,7 на 18,7.
Получаем сколько? Правильно, 18,14. Т.е. на целую часть остается 4 знака. Еще вопросы будут?

читай доку, что такое numeric. в частности хотя бы вот это:
www.ibase.ru/devinfo/migration.htm
там есть примеры и ссылка на полный документ по работе int64.
А то небось, до сих пор думаешь, что 18,7 это 18 в целой части, и 7 в дробной.

p.s. разработчики приложений, пользователи Firebird! Когда начнете читать документацию? Позор!

p.p.s. топик удалить? или оставить для потомков? :)

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 06 фев 2007, 14:26

Здравствуйте, Дмитрий!
Ответ понятен. я сам так иногда отвечаю, когда тупые пользователи не те кнопки жмут в моих программах и говорят, что программа никуда не годится.
Однако: при делении 18,7 на 18,7 получится не 18,14 - это при умножении будет 18,14 а при делении число дробных знаков может быть бесконечным.
Документация по переходу на д3 давно изучена мною и др. сотрудниками компании (иначе бы и не брались переносить софт).
Тот факт, что умножение NUMERIC в IB сделано неправильно не отрицают и разработчики FB (только исправлять пока не торопятся). Ещё в институте проходили, что оно обязано выполняться на двойном регистре. Но зачем деление-то страдает?
Если при делении получается 100 000 возникает переполнение, но если 10 000, то переполнения нет. я догадываюсь, что причина та же, что и при умножении, и знаю почему деление нормально проходит, если результат 10000 (хотя оно вовсе не вписывается в 18,14). но доколе?
И в оракле, и в mssql нормально работают умножение и деление NUMERIC.
И кто здесь должен стыдиться? У меня в софте много своих ошибок и я их стыжусь.
Про ошибки в IB(FB) всегда умалчиваю, чтобы не понимать на смех любимую СУБД; всегда с пеной у рта доказываю что FB самая лучшая СУБД.
Разработчики, ИСПРАВЬТЕ!
или уже все поправлено в FB2.0 ? тогда извиняюсь:\

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 06 фев 2007, 14:35

Володя Т. писал(а):Разработчики, ИСПРАВЬТЕ!
Если проблема так достала, почему бы не прислать разработчикам готовый патч?.. Или спонсировать разработку патча кем-то другим...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 15:45

Однако: при делении 18,7 на 18,7 получится не 18,14 - это при умножении будет 18,14 а при делении число дробных знаков может быть бесконечным.
это откуда такое мнение?
http://www.ibphoenix.com/main.nfs?a=ibp ... act_num_fs
If two operands OP1 and OP2 are exact numeric with scale S1 and S2 respectively, then OP1+OP2 and OP1-OP2 are exact numeric with precision 18 and scale the larger of S1 and S2, while OP1*OP2 and OP1/OP2 are exact numeric with precision 18 and scale S1+S2.
Документация по переходу на д3 давно изучена мною и др. сотрудниками компании (иначе бы и не брались переносить софт).
хреново, видать, изучена.
Тот факт, что умножение NUMERIC в IB сделано неправильно
опять же, на основании чего сделан такой вывод?
The scales of these operation except division are specified by the SQL standard. The standard makes the precision of all these operations, and the scale of divison, implementation-defined: we define the precision as 18, and the scale of division as S1+S2, the same as is required by the standard in the case of multiplication.
И в оракле, и в mssql нормально работают умножение и деление NUMERIC.
там учет масштаба идет по другому. implementation defined, и не обязательно в соответствии со стандартом.

p.s. а стыдиться надо того, что Вы не читаете документы, которым уже как минимум 6 лет. Пусть даже то, что там изложено, Вам не нравится по каким-либо причинам, или кажется Вам неправильным.
Предложите свой вариант, вместо того чтобы тыкать в "неправильность" или кричать "исправьте".

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 06 фев 2007, 16:54

Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности. В данном случае результат должен вычисляться как целое число в 128 бит. После вычисления результат пишется в какую либо переменную или параметр, и лишь на этом этапе должен быть сделан вывод о том наступило переполнение или нет.
В данном случае результат потрясает:
Число 100000.0 делем на 1.0 и получаем integer overflow. При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
Мы конечно найдём как обойти это дело, и я конечно буду продолжать хвалить IB(FB) как я всегда делал раньше, но обидно... :(

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 17:26

Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности.
Володя, предлагаю Вам прекратить эти безобразия. Вы код Firebird смотрели? Какие "числа" Вы делите, получая overflow, и какой typecast Вы ожидаете при этом получить? Вы аргументированно можете описать претензии?
При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
разумеется. потому что результат все равно надо запихивать в smallint, integer или int64. А если он туда не помещается? Какая разница, на этапе записи в integer произойдет переполнение, или на этапе операции над двумя integer?

p.s. я в курсе, что к примеру в Delphi операции для вещественных чисел производятся в extended. Но с целочисленными типами данных не все так просто - в сервере нет int128, а преобразовывать результат в вещественный тип и обратно грозит потерей точности. Не все так просто, Володя. И вопрос этот разработчиками обсуждался. Но к единому мнению, насколько я в курсе, так и не пришли.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 06 фев 2007, 17:40

Володя Т. писал(а):Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности
А то, что бывают процессоры без регистров, вас не учили ? :)
Володя Т. писал(а):В данном случае результат должен вычисляться как целое число в 128 бит
Кому должен ? Нужно в суд подавать, раз должен и не отдаёт ;)
Володя Т. писал(а):В данном случае результат потрясает:
Число 100000.0 делем на 1.0 и получаем integer overflow. При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
Это совершенно не данный случай
Володя Т. писал(а):Мы конечно найдём как обойти это дело, и я конечно буду продолжать хвалить IB(FB) как я всегда делал раньше, но обидно... :(
Гм. Хвалить никто не заставляет, впрочем как и ругать.
Если есть желание заняться 'длинной' арифметикой в FB - можете заняться, никто мешать не будет :)

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 06 фев 2007, 18:19

Типа int128 и не должно быть. Ни в одной ахитектуре ЭВМ не предусмотрено для специального регистра для мультипликативных операций над максимально возможными числами (ну может где-то и предусмотрено, но далеко не везде); его эмулируют. И тип int128 легко может быть сэмулирован с помошью двух int64.
Тему можно считать закрытой. Однако, прошу не удалять.
Пойду искать все операции деления в своих триггерах/процедурах и приписывать к знаменателю cast( as double precision). Может быть поедет.
ps. процессор без регистра? какая разница. всё равно он на чём то считает. регистр - понятие растяжимое

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 06 фев 2007, 19:04

нормальное умножение и деление нумериков планируется в 3.0

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 07 фев 2007, 11:36

Спасибо, dimitr!
Сейчас пока обойдём проблему, а вообще будем ждать :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 07 фев 2007, 13:07

а вообще будем ждать
т.е., сформулировать, чего надо - не получилось?
а то ведь потом опять будут крики "исправьте, нам так не надо!".

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 09 фев 2007, 19:20

Думаю, что dimitr прекрасно понял о чём я говорю.
А если кто-то не понял, попытаюсь повторить проще:
надо чтобы эта процедура выполнялась без ошибок

create procedure test returns (c numeric(18,7))
as
declare variable A numeric(18,7);
declare variable B numeric(18,7);
begin
A = 100000;
B = 1;
C = A / B;
end

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 09 фев 2007, 21:30

это лишь часть проблемы

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 09 фев 2007, 22:37

А если кто-то не понял, попытаюсь повторить проще:
надо чтобы эта процедура выполнялась без ошибок
это ты не понял. я тебе объясняю, что как в текущей реализации, так и вообще, деление 18,7 на 18,7 не может дать результат 18,7 БЕЗ ОКРУГЛЕНИЯ. Это непонятно?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 09 фев 2007, 22:59

Володя Т. писал(а): А если кто-то не понял, попытаюсь повторить проще:
надо чтобы эта процедура выполнялась без ошибок
И только-то?
dimitr писал(а): это лишь часть проблемы
Рыдалъ :lol:

Володя Т.
Сообщения: 16
Зарегистрирован: 02 авг 2005, 19:35

Сообщение Володя Т. » 13 фев 2007, 17:18

Конечно часть проблемы. Но деление, согласитесь, делается очень просто. Чем деление двух чисел 18,7 отличается от деления двух 18,0 друг на друга? С умножением сложнее, там при расчёте двойную точность надо использовать, но это тоже задача, если не из школьной олимпиады, то уж в мифи лет 20 назад мы такие точно проходили.
Дмитрий, конечно С ОКРУГЛЕНИЕМ, а как же? Оно и сейчас работает с округлением, например:

create procedure test returns (c numeric(18,7)) as
declare variable A numeric(18,7);
declare variable B numeric(18,7);
begin
A = 10000;
B = 6;
C = A / B;
end

нормально округляет, получается:

1666.6666667

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 13 фев 2007, 17:30

Владимир, не делайте таких пауз, пожалуйста.
И потом, Ваши намеки уже утомили. Вы если хотите что-то порекомендовать поменять в сервере, сформулируйте Ваши пожелания. Или пишите напрямую в баг-трекер, с описанием проблемы (если не найдете похожее). Мне надоели эти умничанья про школьные олимпиады, МИФИ и прочее.

Ответить