产品超出范围

时间:2013-11-05 03:44:36

标签: c++ for-loop range

我正在尝试为此

编写一个小循环

enter image description here

Pi是(如果你不知道,只是彻底)在k范围内的论证的产物。 Sorta喜欢总和标志。无论如何,我似乎无法绕过如何写这个。我写过这个小功能,但它不是我想要的。它只是在我指定的范围内打印(7i - 2)的结果。它并没有将它们全部放在一起,我知道我没有要求它这样做。我甚至不确定如何要求它这样做。寻找提示,不一定是答案(尽管如此,这也很好)。

到目前为止我做了什么:

void prod(long int& num)
{
    for ( int i = 1; i <= 25; ++i)
    {
        num =(-1.0)*((7.0*i - 2));

        std::cout << num << std::endl;

    }
}

4 个答案:

答案 0 :(得分:3)

这是一个有趣的问题,但需要指出一些问题。首先,nhgrif发布的算法是正确的(并且被接受为这样),但请记住,对于给定的“product”函数,“int”和“long”返回值都会很快溢出,所以代码实际上从未实际给出了k = 25的正确答案。实际上,对于int类型,所述算法仅给出正确的答案,直到k = 7,即1838865600(在我的机器上)。之后,对于k> = 8,数值不正确。

这可以通过运行nhgrif的算法来看到prod()函数的输出显示为up up = k = 10:

i = 1: -5
i = 2: -60
i = 3: -1140
i = 4: -29640
i = 5: -978120
i = 6: -39124800
i = 7: -1838865600
i = 8: -2147483648
i = 9: -2147483648
i = 10: -2147483648
.
.
.

从上面我们看到int的最大值(大小)在i = 8时很快达到,可以通过运行来检查:

#include <iostream>
#include <limits>

int main(int argc, const char * argv[]) 
{    
    int maxInt = std::numeric_limits<int>::max();
    std::cout << "max: " << maxInt << std::endl;
    return 0;
}

给出预期值:

max: 2147483647

我们还看到,对于长数据类型,我们有相同的问题,但可以使其达到k = 12,直到长度的限制被命中为k = 13,即:-9223372036854775808。

底线是上面发布的代码给出了Matt最初请求的k = 25值的错误答案。

解决方案是使用字符串表示数字。这种字符串表示通常用于超出普通数据类型限制的大量数字(例如,Rubik立方体状态的数量或一克碳中的原子数)。但我认为这可能需要一点思考,因为计算需要表示为对字符串的操作,以避免直接处理整数和长期。

有趣的是,Matt给出的函数直接求解为任意k的闭合形式解:

enter image description here

用Gamma函数表示,这需要一些额外的代码在C ++中定义(但C ++ 11定义了它)。

作为参考,对于k = 25,Matt的prod()函数的答案是: -6472463290438308956636841782995191201792000000

为了它的价值,你也可以递归地编写算法:

#include <iostream>

long prod(int k);

int main(int argc, const char * argv[])
{
    int k = 10;
    for (int i = 1; i <= k; i++) {
        std::cout << "i = " << i << ": " << -prod(i) << std::endl;
    }

    return 0;
}

long prod(int k) {
    if (k == 1) {
    return 5;
    }
    else {
        return (7*k - 2)*prod(k - 1);
    }
}

但是这段代码也有上面讨论过的溢出问题。

答案 1 :(得分:2)

num = 1;    
for (int i=1; i <= 25; ++i)
{
    num *= ((7.0*i - 2));
    std::cout << -num << std::endl;
}
num *= -1;
std::cout << num << std::endl;

微妙的差异。

*=运算符就像这样......

A *= B;

与写这个完全一样......

A = A * B;

它将左侧的值乘以右侧的值,并将其赋值给左侧的值。

您可以对所有数学运算符执行相同的操作:+=-=*=/=%=


编辑:作为一个注释,正如bruce3141的回答所指出的那样,intlong long数据类型都会在到达{{{{}}之前导致溢出1}},就目前而言,虽然这个算法是正确的,但由于溢出,它不会在计算机中给出正确的结果。使用诸如k = 25之类的浮点数据类型确实不是可接受的解决方案。您需要查看一个可以处理大于double将存储的整数的类。我不确定long long有什么,但你正在寻找的东西相当于C++的{​​{1}}类。

答案 2 :(得分:1)

num初始化为1,然后将其放入while

num = num*((7.0*i - 2));

最后将其乘以-1

答案 3 :(得分:-1)

double prod(unsigned int k)
{
    double result = 1;
    for(int i = 1; i <= k; i ++)
    {
        result * = 7*i - 2;
    }
    return -result;
}

您可以将其用作:

std::cout<<prod(25);

工作原理:

for(int i = 1; i <= k; i ++)
    {
        result * = 7*i - 2;
    }

计算表达式的pi部分 由于-1不在pi表达式中,所以我只将结果乘以-1一次,然后在return语句中返回它:

return -result;

编辑:

每个数学表达式(没有未知数)总是等于单个值。因此,最好通过使函数返回表达式的值来表示该表达式。返回一个值使得该函数比仅将值打印到控制台更具可重用性 例如。我可以做一些像 double x = prod(3) + prod(4);

这样的事情

由于有一个未知(上限k),我将其作为函数的参数,以便代码可以使用不同的k值。

遵循良好的设计模式总是好的,以避免以后通过重新分解代码来浪费时间。