cast as numeric

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

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

Ответить
Prog
Сообщения: 12
Зарегистрирован: 15 июл 2009, 11:01

cast as numeric

Сообщение Prog » 11 авг 2009, 20:32

Наткнулся на дурацкую проблему с делением-округлением "больших" числел:

Код: Выделить всё

select
  cast(-6000000 as numeric(17,8)) / cast(32 as numeric(5,2)),
  cast(-6000000 as numeric(17,8)) / cast(32 as numeric(17,5)),
  cast(-6000000 as numeric(17,9)) / cast(32 as numeric(5,2))
from rdb$database
Результат:
-187500 2732.04826012975 -14561.774308973
Вроде всё должно быть просто: либо запрошенной точности хватает и тогда всё считается, либо нет и тогда вываливается numeric overflow. А тут ни то ни сё: молча пишет в базу неверные значения..

И вообще, какой тип стоит использовать для денег, с учётом высокой требуемой точности, наличия математических операций и приличного разброса по
суммам?

IB 7.5

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: cast as numeric

Сообщение WildSery » 11 авг 2009, 21:54

Код: Выделить всё

ISQL Version: WI-V2.1.1.17910 Firebird 2.1
SQL> select
CON>   cast(-6000000 as numeric(17,8)) / cast(32 as numeric(5,2)),
CON>   cast(-6000000 as numeric(17,8)) / cast(32 as numeric(17,5)),
CON>   cast(-6000000 as numeric(17,9)) / cast(32 as numeric(5,2))
CON> from rdb$database;

               DIVIDE                DIVIDE                DIVIDE
===================== ===================== =====================
   -187500.0000000000 -187500.0000000000000   -187500.00000000000

Prog
Сообщения: 12
Зарегистрирован: 15 июл 2009, 11:01

Re: cast as numeric

Сообщение Prog » 13 авг 2009, 14:22

Да, я знаю, что FB2.1 во многом превосходит IB7.5..

И всё же, остаётся практический вопрос: какой тип стоит использовать для денег?

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

Re: cast as numeric

Сообщение kdv » 14 авг 2009, 02:16

numeric. только предварительно все-таки надо внимательно прочитать http://www.ibphoenix.com/main.nfs?a=ibp ... act_num_fs , и поэтому не использовать при перемножении и делении numeric(15,8) и т.п. В numeric(15,8) цифра 8 означает МАСШТАБ, т.е. умножение числа на 10^8 при сохранении в целом числе на сервере, и деление на 10^8 при возврате его клиенту. В данном случае переполнения неизбежны, если перемножать или делить здоровенные числа, да еще для них указывать немеряное кол-во знаков после десятичной точки.

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

Re: cast as numeric

Сообщение Dimitry Sibiryakov » 14 авг 2009, 12:56

Интересно, а в какой это стране деньги считают с точностью до 8 знаков после запятой?..

Prog
Сообщения: 12
Зарегистрирован: 15 июл 2009, 11:01

Re: cast as numeric

Сообщение Prog » 14 авг 2009, 19:47

kdv, спасибо за прямую ссылку. Но всё же, как можно в общем случае "не использовать при перемножении и делении numeric(15,8)", если в процедуре надо обработать число из такого поля? Или имелся в виду какой-то другой numeric?

Dimitry Sibiryakov:

Имхо все, у кого есть деньги, считают их с приличной точностью ;)

Вот, например, есть миллион записей о списаниях со счёта, по -0.002 евро каждая. Надо посчитать сумму, добавить какой-нибудь налог и вывести это в рублях "по курсу" (курс, как минимум, с точностью (7,4); налог тоже не меньше чем (4,2)). Если считать в еврокопейках (18,2), то сумма так и будет ноль.

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

Re: cast as numeric

Сообщение Dimitry Sibiryakov » 15 авг 2009, 12:20

Движение по валютному счёту может быть и происходит в 18.4 (хотя лично я не видел банка, позволяющего списать 0.002 евро). Сумма, стало быть, тоже 18.4. Курс рубля - 8.4, что даёт 18.8, правильно. Но! По налоговому кодексу суммы округляются до копеек, так что 18.8 превращаются в 18.2 ДО начисления налога. Налог 4.2, что даёт 18.4. Но! Налоги тоже округляются до копейки, так что результат должен быть 18.2 и ни цифрой после запятой больше.

Ответить