Суммирование числа с плавающей точкой теряет точность при преобразовании типов

Я попытался добавить две цифры с разным весом. Вот мой код:

void onTimeStepOp::updatePointsType1_2(boost::tuples::tuple<float,int,int,int> &_prev,
boost::tuples::tuple<float,int,int,int> &_result,
boost::tuples::tuple<float,float> weights)
{
_result.get<0>() = _result.get<0>() * weights.get<0>() + _prev.get<0>() * weights.get<1>();
std::cout<<"deb:"<<(float)_result.get<2>() * weights.get<0>()<<" "<<(float)_prev.get<2>() * weights.get<1>()<<std::endl;
_result.get<2>() = (int)((float)(_result.get<2>()) * weights.get<0>() + (float)(_prev.get<2>()) * weights.get<1>());
std::cout<<"deb2:"<<(float)_result.get<3>() * weights.get<0>() <<" "<< (float)_prev.get<3>() * weights.get<1>()<<std::endl;
_result.get<3>() = (int)((float)(_result.get<3>()) * weights.get<0>() + (float)(_prev.get<3>()) * weights.get<1>());
}

weights.get<0> = 0,3, weights.get<1> = 0,7.

Вывод, который я получаю, выглядит следующим образом:

resultBefore=36.8055 4 69 91 previousPPos=41.192 4 69 91
deb:20.7 48.3
deb2:27.3 63.7
resultAfter=39.8761 4 **68** 91

Третье число должно быть 69 (69 * 0,3 + 69 * 0,7). Однако вместо этого 68. В чем проблема с выражением преобразования типа?

2

Решение

Преобразование в int усечения, так что малейшая ошибка округления может привести к тому, что вы будете единичным. Вместо того, чтобы напрямую конвертировать в intвы можете использовать функцию round,

Я мог бы добавить, что weights.get<0> это конечно не 0,3 и weights.get<1> безусловно, не 0,7, поскольку ни 0,3, ни 0,7 не могут быть представлены в машинной плавающей запятой (по крайней мере, не на любой машине, которую вы, вероятно, будете использовать).

2

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

Вам следует round() вместо того, чтобы просто бросить int, Приведение преобразует все после десятичной точки, и число из-за ошибки округления может быть что-то вроде 68.99999999991 (только пример, но дает идею).

0

Кастинг в int будет приводить число перед точкой, поэтому 68.1..68.9 будет все 68 как написано ранее.
Другое решение может быть, что не так приятно, это добавить 0.5 на ваш float значение до кастинга. Так 68.1 будет 68.6, который будет еще 68, но 68.5 будет 69 которые будут 69,

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