Добрый день. Написал скрипт для сбора стоимости звонков и записи их в CSV файлик.
Есть переменная $amount_nds - стоимость звонка с уже включенным НДС 18%. Данные о стоимости собираются из базы.
Я прохожу скриптом по таблицам и собираю стоимость каждого звонка и потом выгружаю в CSV-файл.
Проблема в том, что помимо стоимости с НДС, которая уже есть, мне нужно из этой стоимости вычислить для каждого звонка стоимость БЕЗ НДС. Соответственно, я в цикле вычисляю значение без НДС и кладу в переменную $amount ($amount = $amount_nds / 1.18).
Потом если подсчитать в Excel SUM() ячеек со значениями без НДС, то получается отклонение от нужной суммы ячеек на 2-3 копейки. Ну а значение с НДС соответственно все нормально.
Заметил вот что, если писать в csv не округленные до 2 значения, то в итоге SUM() становится верной (и это правильно же: сначала все складываем, а результат уже округляем до нужного). Но, принимающим этот отчет нужно чтобы все записи были уже округлены до 2 знаков после запятой (как рубли.копейки). И в таком случае у меня сумма без НДС получается неверной.
Вот банальный пример:
$query = $db->prepare("SELECT amount FROM table");
$query->execute();
$data = $query->fetchAll(PDO::FETCH_ASSOC);
$sum = 0; // общая сумма без НДС
$sum_nds = 0; // общая сумма с НДС
foreach ($data as $row) {
$amount_nds = $row['amount']; // стоимость с НДС
$amount = round($amount_nds / 1.18, 2); // Вычисляем сумму без НДС
$sum = $sum + $amount;
$sum_nds = $sum_nds + $amount_nds;
file_put_contents("test.csv", $amount . ";" . $amount_nds . "\r\n", FILE_APPEND);
}
echo "---------------------------------\r\nСумма: $sum | Сумма с НДС: $sum_nds\r\n";
В итоге получился вывод:
---------------------------------
Сумма: 4125.98 | Сумма с НДС: 4868.98
А
Сумма должна была быть
4126.25
И соответственно если я не округляю каждое значение, а лашь итоговое то все считается правильно. Но, мне нужно писать округленные до 2 данные. И чем больше записей тем больше разница.
Ведь есть верное решение. В чем секрет? Помогите
UPD
Из ответов понятно, что в базе данные о цене звонка НЕ ДОЛЖНЫ быть с типом float или double, как у меня.
Но это пишет биллинг. Я с этим ничего не поделаю.
Вопрос: получается мне ничего не остается, как жить с этой погрешностью в несколько копеек? Ведь, как бы я не обрабатывал числа с точкой, от этого их точность не улучшится? Прошу окончательного ответа.