我仍然没有通过足够的测试运行它,但由于某种原因,使用某些非负值,此函数有时会传回负值。我在计算器中做了很多手动测试,但是我还没有显示出相同的行为。
我想知道是否有人会看看我是否遗漏了什么。
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返回的浮点数。
所以现在的问题是,如何阻止这个公式呢?即使在Calculator中使用非常高的值进行测试也从未显示过此行为。编译器如何处理导致此操作的操作顺序或者我的值是否只是过高?
答案 0 :(得分: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。
答案 1 :(得分:0)
抛出异常:
if (pPStore > static_cast<float>(INT_MAX)) {
throw std::overflow_error("exceeds integer size");
} else {
pPMax = static_cast<int>(pPStore);
}
或使用float而不是int。
答案 2 :(得分:0)
当你将每个项的最大值相乘时,得到一个大约1.42312e+12
的值,这个值比一个32位整数可以容纳的大一些,所以让我们看一下标准对浮点到标准的看法整数转换,在4.9/1
中:
浮点类型的prvalue可以转换为a的prvalue 整数类型。转换转发;也就是说,小数部分 被丢弃了。如果截断值不能,则行为未定义 用目的地类型表示。
因此,我们了解到,对于函数可以生成的大部分可能结果值,转换回32位整数将是未定义的,包括产生负数。
这里有几个选项。您可以使用64位整数类型(可能long
或long long
)来保存值,而不是截断为int
。
或者,您可以将函数的结果缩小大约1000左右,以使最大结果保持在32位整数可以容纳的值范围内。