【问题标题】:std::_throw_out_of_range occurs from nowherestd::_throw_out_of_range 不知从何而来
【发布时间】:2015-09-27 11:09:05
【问题描述】:

我是 C++ 的绝对初学者。字面上地。这才一个星期。 今天我正在编写一个程序来测试需要多少次迭代才能使某个数字成为回文。 代码如下:

#include <iostream>
#include <string>
#include <algorithm>

/*  This program calculates the steps needed
    to make a certain number palindromic.
    It is designed to output the values for
    numbers 1 to 1000
*/
using namespace std;

class number
{
public:
    string value;
    void reverse();
};

void number::reverse()
{
    std::reverse(value.begin(),value.end());
}

void palindrome(number num)
{
    string n=num.value;
    number reversenum, numsum, numsumreverse;
    reversenum=num;
    reversenum.reverse();
    numsum.value=num.value;
    numsumreverse.value=numsum.value;
    numsumreverse.reverse();
    int i=0;
    while (numsum.value.compare(numsumreverse.value) !=0)
    {
        reversenum=num;
        reversenum.reverse();
        numsum.value=to_string(stoll(num.value,0,10)+stoll(reversenum.value,0,10));
        numsumreverse.value=numsum.value;
        numsumreverse.reverse();
        num.value=numsum.value;
        i++;
    }
    cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
}

int main()
{
    number temp;
    int i;
    for (i=1; i<1001; i++)
    {
        temp.value=to_string(i);
        palindrome(temp);
    }
    return 0;
}

对于高达 195 的数字,它运行顺利。但是,如果是 196,我会收到错误消息。 它说:

在抛出 'std::out_of_range' 的实例后调用终止 什么():斯托尔

我不知道该怎么做。我尝试从196 开始,但错误仍然存​​在。任何帮助将不胜感激。 :)

更新:这次我尝试使用 ttmath 库。但是啊!它再次停在 195 处,甚至不报告错误!我可能正在做一些愚蠢的事情。任何 cmets 将不胜感激。这是更新的代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <ttmath/ttmath.h>

/*  This program calculates the steps needed
    to make a certain number palindromic.
    It is designed to output the values for
    numbers 1 to 1000
*/
using namespace std;

class number
{
public:
    string value;
    void reverse();
};

void number::reverse()
{
    std::reverse(value.begin(),value.end());
}

template <typename NumTy>
string String(const NumTy& Num)
{
    stringstream StrStream;
    StrStream << Num;
    return (StrStream.str());
}

void palindrome(number num)
{
    string n=num.value;
    number reversenum, numsum, numsumreverse;
    reversenum=num;
    reversenum.reverse();
    numsum.value=num.value;
    numsumreverse.value=numsum.value;
    numsumreverse.reverse();
    ttmath::UInt<100> tempsum, numint, reversenumint;
    int i=0;
    while (numsum.value.compare(numsumreverse.value) !=0)
    {
        reversenum=num;
        reversenum.reverse();
        numint=num.value;
        reversenumint=reversenum.value;
        tempsum=numint+reversenumint;
        numsum.value=String<ttmath::UInt<100> >(tempsum);
        numsumreverse.value=numsum.value;
        numsumreverse.reverse();
        num.value=numsum.value;
        i++;
    }
    cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
}

int main()
{
    number temp;
    int i;
    for (i=196; i<1001; i++)
    {
        temp.value=to_string(i);
        palindrome(temp);
    }
    return 0;
}

更新:已解决。一些研究表明 196 可能是Lychrel Number。我在暗示 ttmath 库后得到的结果只是让我确信我的算法有效。我已经尝试了所有高达 10000 的数字,它给出了完美的结果。这是最终代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <ttmath/ttmath.h>
#include <limits>

/*  This program calculates the steps needed
    to make a certain number palindromic.
    It is designed to output the values for
    numbers inside a desired range
*/
using namespace std;
string LychrelList;
int LychrelCount=0;

class number
{
public:
    string value;
    void reverse();
};

void number::reverse()
{
    std::reverse(value.begin(),value.end());
}

template <typename NumTy>
string String(const NumTy& Num)
{
    stringstream StrStream;
    StrStream << Num;
    return (StrStream.str());
}

void palindrome(number num)
{
    string n=num.value;
    number reversenum, numsum, numsumreverse;
    reversenum=num;
    reversenum.reverse();
    numsum.value=num.value;
    numsumreverse.value=numsum.value;
    numsumreverse.reverse();
    ttmath::UInt<100> tempsum, numint, reversenumint;
    int i=0;
    while ((numsum.value.compare(numsumreverse.value) !=0) && i<200)
    {
        reversenum=num;
        reversenum.reverse();
        numint=num.value;
        reversenumint=reversenum.value;
        tempsum=numint+reversenumint;
        numsum.value=String<ttmath::UInt<100> >(tempsum);
        numsumreverse.value=numsum.value;
        numsumreverse.reverse();
        num.value=numsum.value;
        i++;
    }
    if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl;
    else
    {
        cout << "A solution for " << n << " could not be found!!!" << endl;
        LychrelList=LychrelList+n+" ";
        LychrelCount++;
    }
}

int main()
{
    cout << "From where to start?" << endl << ">";
    int lbd,ubd;
    cin >> lbd;
    cout << endl << "And where to stop?" << endl <<">";
    cin >> ubd;
    cout << endl;
    number temp;
    int i;
    for (i=lbd; i<=ubd; i++)
    {
        temp.value=to_string(i);
        palindrome(temp);
    }
    if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount;
    cout << endl << endl << "Press ENTER to end the program...";
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    string s;
    getline(cin,s);
    cout << "Thanks for using!";
    return 0;
}

这是一个非常棒的社区。特别感谢Marco A。 :)

再次更新:我设计了自己的 add() 函数,可以减少程序对外部库的依赖。它也导致了更小的可执行文件和更快的性能。代码如下:

#include <iostream>
#include <string>
#include <algorithm>
#include <limits>

/*  This program calculates the steps needed
    to make a certain number palindromic.
    It is designed to output the values for
    numbers inside a desired range
*/
using namespace std;
string LychrelList;
int LychrelCount=0;

string add(string sA, string sB)
{
    int iTemp=0;
    string sAns;
    int k=sA.length()-sB.length();
    int i;
    if (k>0){for (i=0;i<k;i++) {sB="0"+sB;}}
    if (k<0) {for (i=0;i<-k;i++) {sA="0"+sA;}}
    for (i=sA.length()-1;i>=0;i--)
    {
        iTemp+=sA[i]+sB[i]-96;
        if (iTemp>9)
        {
            sAns=to_string(iTemp%10)+sAns;
            iTemp/=10;
        }
        else
        {
            sAns=to_string(iTemp)+sAns;
            iTemp=0;
        }
    }
    if (iTemp>0) {sAns=to_string(iTemp)+sAns;}
    return sAns;
}

void palindrome(string num)
{
    string n=num;
    string reversenum, numsum, numsumreverse;
    numsum=num;
    numsumreverse=numsum;
    reverse(numsumreverse.begin(),numsumreverse.end());
    int i=0;
    while ((numsum.compare(numsumreverse) !=0) && i<200)
    {
        reversenum=num;
        reverse(reversenum.begin(),reversenum.end());
        numsum=add(num,reversenum);
        numsumreverse=numsum;
        reverse(numsumreverse.begin(),numsumreverse.end());
        num=numsum;
        i++;
    }
    if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num << endl;
    else
    {
        cout << "A solution for " << n << " could not be found!!!" << endl;
        LychrelList=LychrelList+n+" ";
        LychrelCount++;
    }
}

int main()
{
    cout << "From where to start?" << endl << ">";
    int lbd,ubd;
    cin >> lbd;
    cout << endl << "And where to stop?" << endl <<">";
    cin >> ubd;
    cout << endl;
    string temp;
    int i;
    for (i=lbd; i<=ubd; i++)
    {
        temp=to_string(i);
        palindrome(temp);
    }
    if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount;
    cout << endl << endl << "Press ENTER to end the program...";
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    string s;
    getline(cin,s);
    cout <<endl << "Thanks for using!";
    return 0;
}

你们在这里帮助了我很多,让我找到了自己的路。谢谢大家。 :)

【问题讨论】:

  • 我怀疑它是从“无处”发生的。您是否考虑过阅读stoll 的文档?这将立即解释问题。

标签: c++ stderr palindrome discrete-mathematics number-theory


【解决方案1】:

溢出 long long,因为num.valuereversenum.value 的最后两个有效值是7197630720180367016 和6107630810270367917,它们加在一起远高于@987654329 的最大大小@(在我的机器上为 9223372036854775807)。这将产生负值并破坏您对stoll的下一次调用

如果转换后的值超出结果类型的范围或基础函数(std::strtol 或 std::strtoll)将 errno 设置为 ERANGE,则抛出 std::out_of_range。

(reference)

  • 如果您想获得下一个最小的回文数,您应该使用另一种方法,例如 I explained here

您可以在此处找到 Live Example

  • 如果您喜欢/必须继续使用您的方法,您应该在字符串上手动添加或使用 bigint 库(再次查看 here 并修改 plusOne()功能随心所欲)

【讨论】:

  • 那么,我应该使用 ttmath 中的 UInt 变量吗?
  • @SayantanSantra 我添加了一个完整的解释,以防您在给定输入数字N 的情况下尝试找到下一个最小的回文,如果您希望继续使用您的方法,还可以添加一个备用解决方案。如果UInt 代表unsigned integer,那也无济于事。在这里查看range of values。使用unsigned long long 可以帮助您超越该值,但我建议使用我已经解释过的不同方法。
  • 其实我想看看需要多少步才能把一个数字变成一个回文。你知道,有一个猜想,每一个自然数都可以通过有限多步变成回文。
  • 很好,如果您需要按照自己的方式进行操作,那么您将不得不使用我发布的链接中的手动添加(如果您正在处理大整数则需要)或使用库专门为此目的。
  • 嗯...我安装了 ttmath 库。我认为它会让它工作。到家后一定会试试的。
【解决方案2】:

来自http://www.cplusplus.com/reference/string/stoll/

如果读取的值超出可表示值的范围 long long,则抛出 out_of_range 异常。

ll 数据类型无法处理字符串长度。我的调试器告诉我值有 196 个中断 std::stoll (__str=\"9605805010994805921-\", __idx=0x0, __base=10)

长长的太小了。

您可能希望对字符串本身进行加法,而不是使用数字类型。

【讨论】:

  • 那么,我应该使用 ttmath 中的 UInt 变量吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多