Простое сложение и вычитание не работает правильно

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

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

В приведенном ниже примере он возвращает действительно крошечное число от 53,87 до 53,87, которое должно быть равным нулю. Оно было убрано, чтобы устранить другие причины, вызывающие проблемы, поэтому я удалил большую часть проверки ввода и т. Д.

<?php $inputs = array(
array(
"in" => '',
"out" => '249.6',
),
array(
"in" => '',
"out" => '396',
),
array(
"in" => '554.4',
"out" => ''
),
array(
"in" => '145.07',
"out" => ''
),
array(
"in" => '',
"out" => '53.87',
),
);
$fTotal = 0;
echo "Start at 0:   ";
foreach($inputs as $key=>$sRef) {
$itemValid = true;
$aItem = array();
$amountIn = $inputs[$key]['in'];
$amountOut = $inputs[$key]['out'];
if ($itemValid) {
echo "'".$fTotal."'";
$is_in = 0;
if ($amountIn > 0.0) {
$is_in = 1;
echo "+";
$amount = $amountIn;
$fTotal = $fTotal + $amountIn;
} else {
$is_in = 0;
echo "-";
$amount = $amountOut;
$fTotal = $fTotal - $amountOut;
}
echo "'".$amount."'=";
echo "'".$fTotal."'   |   ";
$aItem["is_in"] = $is_in;
$aItem["amount"] = $amount;
$aItems[] = $aItem;
}
}

Вы можете запустить это в песочнице Вот.

Вот ожидаемый результат:

Начните с 0: «0» — «249,6» = «- 249,6» | ‘-249,6’ — ‘396’ = ‘- 645,6’ | ‘-645,6’ + ‘554,4’ = ‘- 91,2’ | ‘-91,2’ + ‘145,07’ = ‘53,87’ | ‘53,87 ‘-‘ 53,87 ‘=’ 0 ‘|

Вот фактический результат:

Начните с 0: «0» — «249,6» = «- 249,6» | ‘-249,6’ — ‘396’ = ‘- 645,6’ | ‘-645,6’ + ‘554,4’ = ‘- 91,2’ | ‘-91,2’ + ‘145,07’ = ‘53,87’ | ‘53,87 ‘-‘ 53,87 ‘=’ — 4,9737991503207E-14 ‘|

Что здесь не так?

Обновить

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

0

Решение

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

Если вы можете утверждать, что каждое число может быть округлено до 2 десятичных знаков, и на основе вашего ограниченного набора данных, оборачивая ваши «суммы» в number_format($fTotal + $amountIn , 2) и т.д. может разобраться в этом для вас.

В качестве альтернативы для «более точного», просто оберните последний, например. echo "'".number_format($fTotal, 2)."' | "; (или 0 или что-то еще)

1

Другие решения

Ваши числа интерпретируются как строки.

Попробуй это:

<?php
$inputs = array(
array(
"in" => 0,
"out" => 249.6,
),
array(
"in" => 0,
"out" => 396,
),
array(
"in" => 554.4,
"out" => 0
),
array(
"in" => 145.07,
"out" => 0
),
array(
"in" => 0,
"out" => 53.87,
),
);

$fTotal = 0;

echo "Start at 0:   ";
foreach($inputs as $key => $sRef) {
$itemValid = true;

$amountIn = $sRef['in'];
$amountOut = $sRef['out'];

if ($itemValid) {

echo $fTotal;

$is_in = 0;
if ($amountIn > 0.0) {

$is_in = 1;

echo "+";

$amount = floatval($amountIn);
$fTotal = floatval($fTotal) + floatval($amountIn);

} else {

$is_in = 0;

echo "-";

$amount = floatval($amountOut);
$fTotal = floatval($fTotal) - floatval($amountIn);

}

echo $amount;
echo ' = ' . $fTotal . "  |  ";
}

}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector