值等于-1的错误数学?

时间:2018-08-13 20:39:56

标签: c++ rcpp

给出以下基本代码:

double x = 3;
return x *-1;

我希望返回结果为-3。但是,我得到的实际值大约是 1.844674e + 19 (受输出限制)或一个疯狂的大数字。简单地return -x;也行不通。

更改代码:

double x = 3;
return x *-1.0;

返回正确的输出。 这似乎是一些整数与双精度或布尔值问题。 我知道在不将整数显​​式地划分为整数的情况下将整数除可以给出0而不是分数,但是我从未见过它会导致乘法或加法问题。

有人能告诉我发生了什么事或指向行为解释以及如何处理吗?

编辑:这是我机器上的可验证示例。

功能:

// [[Rcpp::export]]
double test1(double data)
{
  std::vector<double> testArray(data);
  return (testArray.size()*-1);
}

从R运行:

test1(4)

结果:

[1] 1.844674e+19

我能够将问题缩小到向量的大小。因此,对于任何正整数大小,.size()函数乘以-1都会得出疯狂的值。乘以-1.0可以很好地工作。

编辑2:我想我明白了。 Toby是正确的,它是一个无符号值,不会转换为double。 在我的原始样本中:

// [[Rcpp::export]]
double test1(double data)
{
  std::vector<double> testArray(data);
  double arraySize = testArray.size();
  return (arraySize*-1);
}

先将其转换为双精度并乘以-1.0即可,效果也很好。

1 个答案:

答案 0 :(得分:1)

尽管您认为自己的代码与此类似:

#include <iostream>

double f()
{
    double x = 3;
    return x * -1;
}

int main()
{
    std::cout << f() << std::endl;
}

您实际上拥有的代码从向量x的结果中提取size()的类型-这将返回std::size_t

#include <cstdint>
#include <iostream>

double f()
{
    std::size_t x = 3;
    return x * -1;
}

int main()
{
    std::cout << f() << std::endl;
}

这里发生的是将std::size_t乘以int。当一个论点被签名而一个未签名时的晋升规则表明(来源:CppReference

  

如果无符号操作数的转换等级大于或等于有符号操作数的转换等级,则将有符号操作数转换为无符号操作数的类型。

std::size_t的排名通常高于int,因此我们现在将3乘以(std::size_t)-1-这是一个很大的数字。然后,当我们return时,这个大数字将转换为double以匹配f()的签名。

可以通过几种方法避免该问题:

  • size()的结果存储到有符号或浮点类型的变量中,并使用它进行乘法。
  • 乘法时,使用size()static_cast<>的结果转换为有符号或浮点类型。
  • 乘以浮点常量(例如-1.0)-这将导致另一个参数提升为浮点。