Умножение Энгрса дает неверный результат - PullRequest
0 голосов
/ 29 августа 2018

У меня есть таблица Ingres со следующими столбцами

from_date ingresdate
to_date ingresdate
model_amt money

Даты могут отражать период любого количества дней, а model_amt всегда является недельным значением. Мне нужно отработать итоговую модель_амт за период

Для этого мне нужно знать, сколько дней покрывается периодом, а затем разделить model_amt на 7 и умножить его на количество дней

однако я получаю неправильные результаты, используя код ниже

select model_amt, date_part('day',b.to_date - b.from_date), 
model_amt / 7 * int4( (date_part('day',b.to_date - b.from_date)) )
from table

Например, где model_amt = 88,82 и период составляет 2 недели, я получаю следующий вывод

+-------------------------------------------------------+
¦model_amt           ¦col2         ¦col3                ¦
+--------------------+-------------+--------------------¦
¦              #88.82¦           14¦             #177.66¦
+-------------------------------------------------------+

Но 88,82 / 7 * 14 = 177,64, а не 177,66?

Есть идеи, что происходит? Та же проблема возникает независимо от того, включаю ли я функцию int4 вокруг date_part.

* Обновление 15:28 *

Решением было добавить функцию float8 вокруг model_amt

float8(model_amt)/ 7 * interval('days', to_date - from_date)

Спасибо за ответы.

1 Ответ

0 голосов
/ 29 августа 2018

В компьютерах числа с плавающей точкой общеизвестно неточны. Вы можете умножать все виды базовых математических вычислений на числа с плавающей запятой, и они будут на несколько десятичных знаков.

Некоторую информацию можно найти здесь; но это очень гуглим :). http://effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm

Как правило, чтобы избежать неточностей, вам нужно использовать специфическую для языка функцию (например, BigDecimal в Java), чтобы «идеально» хранить десятичные дроби. Кроме того, вы можете представить десятичные числа в виде отдельных целых чисел (например, главное число - одно целое, а десятичное - другое целое) и объединить их позже.

Итак, я подозреваю, что это всего лишь ingres, показывающий обычные неточности с плавающей запятой, и что в этой базе данных есть известные обходные пути для этого.

Обновление

Вот статья поддержки от Actian специально о проблемах с плавающей запятой, которая кажется полезной: https://communities.actian.com/s/article/Floating-Point-Numbers-Causes-of-Imprecision.

...