проблема суммируемых значений (работа с ошибкой округления) - PullRequest
5 голосов
/ 24 января 2011

У меня есть продукт, который стоит 4 €, и мне нужно разделить эти деньги на 3 отдела. Во втором столбце мне нужно получить количество строк для этого продукта и разделить на количество отделов.

Мой запрос:

select
   department, totalvalue,
   (totalvalue / (select count(*) from departments d2 where d2.department = p.product))
       dividedvalue
from products p, departments d
where d.department = p.department

Department  Total Value  Divided Value
----------  -----------  -------------
A           4            1.3333333
B           4            1.3333333
C           4            1.3333333

Но когда я суммирую значения, я получаю 3,999999. Конечно, с сотнями рядов я получаю большие различия ... Есть ли шанс определить 2 десятичных числа и округлить последнее значение? (мои результаты будут 1,33 1,33 1,34) Я имею в виду, какой-то способ настроить последний ряд?

Ответы [ 4 ]

1 голос
/ 24 января 2011

Чтобы справиться с этим, для каждой строки вам нужно будет сделать следующее:

  • Выполнить деление
  • Округлить результат до соответствующего количества центов
  • Суммируйте разницу между округленной суммой и результатом операции деления
  • Когда сумма разностей превышает наименьшее десятичное число (в данном случае 0,01), прибавьте эту сумму к результатамследующая операция деления (после округления).

Это позволит равномерно распределить дробные суммы по строкам.К сожалению, в SQL нет простого способа сделать это с помощью простых запросов;вероятно, лучше выполнить это в процедурном коде.

Что касается того, насколько это важно, когда речь идет о финансовых приложениях и учреждениях, такие вещи очень важны, даже если это всего лишь на копейку, и даже еслиэто может произойти только через каждое количество записей;как правило, пользователи хотят видеть значения, привязанные к копейке (или к любой другой единице вашей валюты).

Самое главное, вы не хотите допускать такой эксплойт, как "Супермен III" или «Офисные помещения» , которые должны появиться.

0 голосов
/ 29 января 2015

Также это можно сделать, просто добавив разницу округления определенного значения к следующему числу, которое будет округлено (до округления). Таким образом, куча остается всегда одинакового размера.

0 голосов
/ 24 января 2011

С шестью десятичными знаками точности вам потребуется около 5000 транзакций, чтобы заметить разницу в один цент, если вы округлите окончательное число до двух десятичных знаков.Увеличение количества десятичных знаков до приемлемого уровня устранит большинство проблем, т. Е. При использовании 9 десятичных знаков потребуется около 5 000 000 транзакций, чтобы заметить разницу в центах.

0 голосов
/ 24 января 2011

Может быть, вы можете сделать четвертую строку, которая будет Общая сумма (A, B, C).Но это зависит от того, что вы хотите сделать, если вам нужно точное значение, вы можете сохранить дроби, иначе, усечь и не заботиться о виртуальной потере

...