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 之间

pSRand:1 到 1000 之间

pERand:在 1.0f 和 5500.0f 之间,然后乘以 0.001f,然后传递给上面的函数

编辑:

好吧,在更仔细地跟踪执行之后,这不是这个函数的直接错误。它会产生一个无限正的浮点数,然后当我稍后使用此代码时会翻转为负数:

pPMax = (int)pPStore;

pPStore 是一个浮点数,它保存 popCalc 的返回值。

所以现在的问题是,我如何阻止公式这样做?即使在计算器中使用非常高的值进行测试也从未显示过这种行为。编译器如何处理导致这种情况的操作顺序或者我的值只是太高了?

4

3 回答 3

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;
}

正如您在此处看到的,还有其他类型的范围更大。如果这些还不够,我相信最新的 boost 版本正好适合你

于 2013-06-30T04:10:56.340 回答
0

抛出异常:

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

或使用 float 而不是 int。

于 2013-06-30T04:09:55.593 回答
0

当您将每个术语的最大值相乘时,您会得到一个1.42312e+12比 32 位整数可以容纳的值略大的值,所以让我们看看标准对浮点到整数的转换有什么看法,在4.9/1

浮点类型的纯右值可以转换为整数类型的纯右值。转换截断;也就是说,小数部分被丢弃。如果截断的值不能在目标类型中表示,则行为未定义。

因此我们了解到,对于您的函数可以生成的大部分可能的结果值,转换回 32 位整数将是未定义的,其中包括产生负数。

您在这里有几个选择。您可以使用 64 位整数类型(longlong long可能)来保存该值,而不是截断为int.

或者,您可以将函数的结果按比例缩小大约 1000 倍左右,以将最大结果保持在 32 位整数可以容纳的值范围内。

于 2013-06-30T04:25:26.183 回答