【问题标题】:Function Returning Negative Value返回负值的函数
【发布时间】:2013-06-27 12:55:00
【问题描述】:

我仍然没有通过足够的测试运行它,但是由于某种原因,使用某些非负值,这个函数有时会传回一个负值。我已经在计算器中使用不同的值进行了很多手动测试,但我还没有让它显示相同的行为。

我想知道是否有人会看看我是否遗漏了什么。

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 的返回值。

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

【问题讨论】:

  • 我的猜测是你溢出了,这意味着值太大了,由于它在内存中的表示方式,它变成了负数。
  • 什么是产生负输出的输入示例?
  • 请注意,只有整数溢出才会导致否定结果。浮点溢出将导致正无穷大。 int 的大小是多少?
  • @Borgleader 这似乎是正在发生的事情。浮点数变为无限正数,当我稍后将其转换为 int 时会产生负值。
  • 所以问题出在你没有发布的代码上?如果是这样,请发布问题代码,以便我们为您提供适当的帮助。

标签: c++ function floating-point return negative-number


【解决方案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 版本有 just the thing for you

【讨论】:

  • 使用 long long int 有效。基本上,这是我正在开发的 4X 游戏的人口生成测试应用程序,需要能够达到数万亿。根据需要将 int 替换为 long long int,并且我不再显示负值,并且我的截断功能正常工作。谢谢。
【解决方案2】:

抛出异常:

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

或者使用 float 代替 int。

【讨论】:

  • 对,但是如果需要使用整数,那么就差不多了
【解决方案3】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2020-07-20
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    相关资源
    最近更新 更多