Функция, возвращающая отрицательное значение

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

Мне было интересно, если кто-нибудь взглянет на то, что я что-то упускаю.

float calcPop(int popRand1, int popRand2, int popRand3, float pERand, float pSRand)
{
return ((((((23000 * popRand1) * popRand2) * pERand) * pSRand) * popRand3) / 8);
}

Все переменные содержат случайно сгенерированные значения:

popRand1: от 1 до 30

popRand2: от 10 до 30

popRand3: от 50 до 100

pSRand: от 1 до 1000

pERand: между 1.0f и 5500.0f, который затем умножается на 0.001f перед передачей функции выше

Редактировать:

Хорошо, так что после того, как следите за выполнением немного более внимательно, это не ошибка этой функции напрямую. Он генерирует бесконечно положительное число с плавающей точкой, которое затем переворачивается отрицательно, когда я позже использую этот код:

pPMax = (int) pPStore;

pPStore — это число с плавающей точкой, которое содержит возврат popCalc.

Теперь возникает вопрос: как мне остановить формулу от этого? Тестирование даже с очень высокими значениями в Калькуляторе никогда не показывало такого поведения. Есть ли что-то в том, как компилятор обрабатывает порядок операций, который вызывает это, или мои значения просто слишком велики?

0

Решение

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

#include <iostream>
#include <limits>
#include <boost/multiprecision/cpp_int.hpp>

int main(int argc, char* argv[])
{
std::cout << "int min: " << std::numeric_limits<int>::min() << std::endl;
std::cout << "int max: " << std::numeric_limits<int>::max() << std::endl;
std::cout << "long min: " << std::numeric_limits<long>::min() << std::endl;
std::cout << "long max: " << std::numeric_limits<long>::max() << std::endl;
std::cout << "long long min: " << std::numeric_limits<long long>::min() << std::endl;
std::cout << "long long max: " << std::numeric_limits<long long>::max() << std::endl;

boost::multiprecision::cpp_int bigint = 113850000000;
int smallint = 113850000000;
std::cout << bigint << std::endl;
std::cout << smallint << std::endl;

std::cin.get();
return 0;
}

Как вы можете видеть здесь, есть другие типы, которые имеют больший диапазон. Если этого не достаточно, я считаю, что последняя версия Boost имеет только вещь для тебя.

1

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

Бросить исключение:

if (pPStore > static_cast<float>(INT_MAX)) {
throw std::overflow_error("exceeds integer size");
} else {
pPMax = static_cast<int>(pPStore);
}

или используйте float вместо int.

0

Когда вы умножаете максимальные значения каждого члена вместе, вы получаете значение около 1.42312e+12 который несколько больше, чем может содержать 32-битное целое число, поэтому давайте посмотрим, что стандарт должен сказать о преобразованиях с плавающей запятой в целое, в 4.9/1:

Значение типа с плавающей запятой может быть преобразовано в значение типа
целочисленный тип. Конверсионные стволы; то есть дробная часть
отбрасывается Поведение не определено, если усеченное значение не может
быть представленным в типе назначения.

Итак, мы узнаем, что для большого сегмента возможных значений результата, который может сгенерировать ваша функция, преобразование обратно в 32-битное целое число будет неопределенным, что включает создание отрицательных чисел.

У вас есть несколько вариантов здесь. Вы можете использовать 64-битный целочисленный тип (long или же long long возможно) удерживать значение вместо усечения до int,

В качестве альтернативы вы можете уменьшить результаты вашей функции примерно в 1000 раз, чтобы сохранить максимальные результаты в диапазоне значений, который может содержать 32-разрядное целое число.

0
По вопросам рекламы [email protected]