Страница 1 из 1
Деление больших чисел (все глючнее и глючнее)
Добавлено: 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 - будете знать

Добавлено: 29 янв 2007, 21:59
kdv
делим 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. топик удалить? или оставить для потомков?

Добавлено: 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 ? тогда извиняюсь:\
Добавлено: 06 фев 2007, 14:35
Dimitry Sibiryakov
Володя Т. писал(а):Разработчики, ИСПРАВЬТЕ!
Если проблема так достала, почему бы не прислать разработчикам готовый патч?.. Или спонсировать разработку патча кем-то другим...
Добавлено: 06 фев 2007, 15:45
kdv
Однако: при делении 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 лет. Пусть даже то, что там изложено, Вам не нравится по каким-либо причинам, или кажется Вам неправильным.
Предложите свой вариант, вместо того чтобы тыкать в "неправильность" или кричать "исправьте".
Добавлено: 06 фев 2007, 16:54
Володя Т.
Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности. В данном случае результат должен вычисляться как целое число в 128 бит. После вычисления результат пишется в какую либо переменную или параметр, и лишь на этом этапе должен быть сделан вывод о том наступило переполнение или нет.
В данном случае результат потрясает:
Число 100000.0 делем на 1.0 и получаем integer overflow. При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
Мы конечно найдём как обойти это дело, и я конечно буду продолжать хвалить IB(FB) как я всегда делал раньше, но обидно...

Добавлено: 06 фев 2007, 17:26
kdv
Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности.
Володя, предлагаю Вам прекратить эти безобразия. Вы код Firebird смотрели? Какие "числа" Вы делите, получая overflow, и какой typecast Вы ожидаете при этом получить? Вы аргументированно можете описать претензии?
При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
разумеется. потому что результат все равно надо запихивать в smallint, integer или int64. А если он туда не помещается? Какая разница, на этапе записи в integer произойдет переполнение, или на этапе операции над двумя integer?
p.s. я в курсе, что к примеру в Delphi операции для вещественных чисел производятся в extended. Но с целочисленными типами данных не все так просто - в сервере нет int128, а преобразовывать результат в вещественный тип и обратно грозит потерей точности. Не все так просто, Володя. И вопрос этот разработчиками обсуждался. Но к единому мнению, насколько я в курсе, так и не пришли.
Добавлено: 06 фев 2007, 17:40
hvlad
Володя Т. писал(а):Меня учили, что результат мультипликативной операции должен расчитываться на регистре двойной точности
А то, что бывают процессоры без регистров, вас не учили ?
Володя Т. писал(а):В данном случае результат должен вычисляться как целое число в 128 бит
Кому должен ? Нужно в суд подавать, раз должен и не отдаёт
Володя Т. писал(а):В данном случае результат потрясает:
Число 100000.0 делем на 1.0 и получаем integer overflow. При этом не важно в какой тип идёт запись результата переполнение наступает при вычислении.
Это совершенно не
данный случай
Володя Т. писал(а):Мы конечно найдём как обойти это дело, и я конечно буду продолжать хвалить IB(FB) как я всегда делал раньше, но обидно...

Гм. Хвалить никто не заставляет, впрочем как и ругать.
Если есть желание заняться 'длинной' арифметикой в FB - можете заняться, никто мешать не будет

Добавлено: 06 фев 2007, 18:19
Володя Т.
Типа int128 и не должно быть. Ни в одной ахитектуре ЭВМ не предусмотрено для специального регистра для мультипликативных операций над максимально возможными числами (ну может где-то и предусмотрено, но далеко не везде); его эмулируют. И тип int128 легко может быть сэмулирован с помошью двух int64.
Тему можно считать закрытой. Однако, прошу не удалять.
Пойду искать все операции деления в своих триггерах/процедурах и приписывать к знаменателю cast( as double precision). Может быть поедет.
ps. процессор без регистра? какая разница. всё равно он на чём то считает. регистр - понятие растяжимое
Добавлено: 06 фев 2007, 19:04
dimitr
нормальное умножение и деление нумериков планируется в 3.0
Добавлено: 07 фев 2007, 11:36
Володя Т.
Спасибо, dimitr!
Сейчас пока обойдём проблему, а вообще будем ждать

Добавлено: 07 фев 2007, 13:07
kdv
а вообще будем ждать
т.е., сформулировать, чего надо - не получилось?
а то ведь потом опять будут крики "исправьте, нам так не надо!".
Добавлено: 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
Добавлено: 09 фев 2007, 21:30
dimitr
это лишь часть проблемы
Добавлено: 09 фев 2007, 22:37
kdv
А если кто-то не понял, попытаюсь повторить проще:
надо чтобы эта процедура выполнялась без ошибок
это ты не понял. я тебе объясняю, что как в текущей реализации, так и вообще, деление 18,7 на 18,7 не может дать результат 18,7 БЕЗ ОКРУГЛЕНИЯ. Это непонятно?
Добавлено: 09 фев 2007, 22:59
Merlin
Володя Т. писал(а):
А если кто-то не понял, попытаюсь повторить проще:
надо чтобы эта процедура выполнялась без ошибок
И только-то?
dimitr писал(а):
это лишь часть проблемы
Рыдалъ

Добавлено: 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
Добавлено: 13 фев 2007, 17:30
kdv
Владимир, не делайте таких пауз, пожалуйста.
И потом, Ваши намеки уже утомили. Вы если хотите что-то порекомендовать поменять в сервере, сформулируйте Ваши пожелания. Или пишите напрямую в баг-трекер, с описанием проблемы (если не найдете похожее). Мне надоели эти умничанья про школьные олимпиады, МИФИ и прочее.