【问题标题】:Why does pow() in C++ Return a Negative Number为什么 C++ 中的 pow() 返回负数
【发布时间】:2016-09-22 07:25:57
【问题描述】:

使用<cmath> 库中的pow(),我得到一些数字的负数。

2601*((int)pow(10.0,3*2)) = -1693967296

为什么会这样?是因为int 的范围仅在 -32767 到 32767 之间吗?还是因为选角?

【问题讨论】:

标签: c++ pow cmath


【解决方案1】:

您的程序的行为是未定义,因为您正在溢出有符号整数类型。

pow(10.0, 3 * 2)返回负数。该特定重载将返回double。您将其转换为 int 然后将其乘以常数。这太大了,无法放入int。您是否在您的平台上检查了INT_MAX(或等效的std::numeric_limits<int>::max())?

【讨论】:

  • 在我看来 pow 的返回值确实适合 int 并且是乘法溢出。
  • 你是对的。谢谢你指出这一点。我已经确定了答案。
【解决方案2】:

这是因为整数溢出。

2601*1000000 > INT_MAX. 

因此溢出。

【讨论】:

  • 我知道很挑剔,但 INT_MAX 不在 std
【解决方案3】:

不是pow(),而是你抢占了答案。

10 的 6 次方是一百万,一百万乘以 2,601 是

2,601,000,000

对于您平台上的有符号整数,范围可能是

–2,147,483,648 to 2,147,483,647

所以你看,你已经超出了这个范围。实际的溢出差异可能看起来不一致,但这是因为二进制补码形式。

【讨论】:

  • 您的范围适用于 2 的补码 32 位有符号 int
  • 是的,这是真的。我正在对平台做出(可能是错误的)假设。但根据我的经验,这是最常见的。
  • 我知道你真正的意思,但如果你在 C 标签上这么说,你就会有嵌入式系统的家伙在你身后。但说真的,你对范围的断言破坏了这个答案。
【解决方案4】:

是的,这是因为 int 数据类型。 int 范围是 -2,147,483,648 到 2,147,483,647,因为 sizeof(int) 是 4 个字节。

要克服这个问题,您可以使用 unsigned intlong int

【讨论】:

  • "int 范围是从 -2,147,483,648 到 2,147,483,647,因为 sizeof(int) 是 4 个字节"。的确,有时这是正确的。但 C++ 标准并不坚持这一点。更糟糕的是,unsigned 可以小到 0 到 65535,因此在这种情况下无济于事。
  • 是的。对于 16 位编译器系统,无符号可以是 0 到 65535。但是缩小上述问题,发问者使用的是32位编译器系统。如果你有空,看看这个ideone.com/KZagQB:P
  • "long int" 在许多系统上不大于 int。另一方面,“long long int”保证至少为 64 位(实际上是 64 位)。
【解决方案5】:

您的平台似乎具有 32 位 int。这支持 -2147483648 到 2147483647 的范围

pow() 以双精度浮点数返回正数。这一点工作正常。

您的演员将其转换为 int,这也很好。

出错的地方是乘法。乘法溢出,有符号溢出是未定义的行为。

在您的情况下,您似乎最终得到了二进制补码环绕,但您应该知道,这种行为是不能保证的,尤其是对于现代优化编译器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 2018-01-29
    • 2020-04-01
    • 1970-01-01
    相关资源
    最近更新 更多