cplex.getvalue (x) возвращает значение с плавающей запятой, и когда я помещаю значение в int, оно отличается от исходного. Есть ли лучший способ получить доступ к значению целочисленной переменной?
Теперь я просто использую наивный способ и не знаю, правильно это или нет
val = cplex.getObjValue() + 0.1;
for (int i = 0; i < n; i++)
returnX[i] = cplex.getValue(x[i]) + 0.1;
Если вы храните значение с плавающей запятой в целочисленном типе (например, int
), вы потеряете любую точность после десятичной точки. Интегральные типы просто хранят только целые числа. Если вы храните float
в int
, вы потеряете что-либо после десятичной точки.
Если вы добавите 0,1 к float
вы просто получаете значение с плавающей запятой примерно на 0,1 больше исходного значения. Если вы назначите это на int
, у вас будет точно такая же проблема. Вы просто собираетесь усечь другое значение.
Если вам нужно float
чтобы сохранить его точность, просто храните его в float
(или double
для еще большей точности).
Если, возможно, вы делаете конверсию, как int -> float -> int
где оригинал int
имеет одно значение, а значение, которое вы получите в конце, отличается int
Ну, это именно то, что происходит. Преобразование в float
не симметрично. int
в float
преобразование будет преобразовано в ближайшее представимое float
значение, тогда как float
в int
преобразование будет усечено.
Значение типа с плавающей запятой может быть преобразовано в значение типа целого числа. Усечение преобразования; то есть дробная часть отбрасывается. […]
Значение типа integer или перечисления с незаданной областью может быть преобразовано в значение типа с плавающей запятой. Результат точен, если это возможно. Если конвертируемое значение находится в диапазоне значений, которые могут быть представлены, но значение не может быть представлено точно, это определенный реализацией выбор следующего более низкого или более высокого представимого значения. […]
Решение этого заключается в том, чтобы не переходить на промежуточный float
, Если вы хотите int
держи это int
, Если по какой-то причине для вашей функции имеет смысл вернуть float
несмотря на то, что вещь, которую он рассчитал, была int
тогда вы должны принять последствия.
Во-первых, вы потеряете значение точности при приведении его к типу int. Вы можете сделать, это округлить значение.
Пример:
float fVal = 10.89;
int nVal = (fVal > 0.0) ? (fVal + 0.5) : (fVal - 0.5);
Потому что C ++ округляется до нуля (вместо округления до ближайшего), а потому что числа с плавающей запятой хранят приблизительная значение, которое может быть не совсем точным (например, 0.9999997f), тогда вы получите результаты, с которыми вы столкнулись.
Добавление +0,001 — это хорошо. Если вы действительно хотите округлить до ближайшего, добавьте 0.5f, а затем позвольте C ++ округлить до глубины души.
float closerToFive = 5.454f;
float closerToSix = 5.545f;
int five = static_cast<int>(closerToFive + 0.5f);
int six = static_cast<int>(closerToSix + 0.5f);
Может быть, это «наивный путь», но он работает хорошо. Оберните это в func, если вы делаете это много:
constexpr int ftoi(float value)
{
return static_cast<int>(value + (value > 0.0f? 0.5f : -0.5f));
}ftoi(5.454f) -> 5
ftoi(5.545f) -> 6
ftoi(-5.454f) -> -5
ftoi(-5.545f) -> -6
Редактировать: Забыл учесть отрицательные числа с плавающей точкой, как указывает ответ CasperGhost. Исправлена функция ftoi ().