решение — доступ к точному значению интегральной переменной через переполнение стека

cplex.getvalue (x) возвращает значение с плавающей запятой, и когда я помещаю значение в int, оно отличается от исходного. Есть ли лучший способ получить доступ к значению целочисленной переменной?

Теперь я просто использую наивный способ и не знаю, правильно это или нет

val = cplex.getObjValue() + 0.1;

for (int i = 0; i < n; i++)
returnX[i] = cplex.getValue(x[i]) + 0.1;

-3

Решение

Если вы храните значение с плавающей запятой в целочисленном типе (например, 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 тогда вы должны принять последствия.

3

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

Во-первых, вы потеряете значение точности при приведении его к типу int. Вы можете сделать, это округлить значение.

Пример:

float fVal = 10.89;

int nVal = (fVal > 0.0) ? (fVal + 0.5) : (fVal - 0.5);
1

Потому что 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

http://ideone.com/gDT4GP

Редактировать: Забыл учесть отрицательные числа с плавающей точкой, как указывает ответ CasperGhost. Исправлена ​​функция ftoi ().

0