2013-06-30 19 views
0

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

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

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

pSR и: от 1 до 1000

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

Edit:

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

pPMax = (int) pPStore;

pPStore - это поплавок, который возвращает popCalc.

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

+1

Я предполагаю, что вы переполнены, то есть значение настолько велико, что оно становится отрицательным из-за того, как оно представлено в памяти. – Borgleader

+1

Что такое пример ввода, который производит отрицательный вывод? –

+1

Обратите внимание, что только целочисленное переполнение приведет к отрицательному результату. переполнение флота приведет к положительной бесконечности. Каков размер int? –

ответ

1

В этом случае кажется, что, когда вы возвращаетесь обратно к 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; 
} 

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

+0

Использование long long int работает. В основном это тестовое приложение для генерации популяций для игры 4X, над которой я работаю, и чтобы она могла подняться на триллионы. Замененный int для long long int по мере необходимости, и у меня больше нет отрицательных значений, и моя функция усечения работает правильно. Благодарю. – Geowil

0

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

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

или использовать поплавок вместо междунар.

+0

Это не решает проблему. – Borgleader

+0

правильно, но если требуется целое число, то это в значительной степени это, хотя – perreal

0

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

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

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

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

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

Смежные вопросы