std :: _ throw_out_of_range происходит из ниоткуда

Я абсолютный новичок в 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’
что (): stoll

Я не могу разобрать, что делать. Я пытался начать с 196 но ошибка сохранилась. Любая помощь будет оценена. 🙂

ОБНОВЛЕНИЕ: На этот раз я попытался сделать это с помощью библиотеки ttmath. Но, аааа! Он снова останавливается на 195 и даже не сообщает об ошибке! Я мог бы делать что-то глупое. Любые замечания будут оценены. Вот обновленный код:

#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 может быть Лихрелый номер. И результат, который я получил после намека на то, что библиотека 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;
}

Это действительно потрясающее сообщество. Особая благодарность Марко А. 🙂

ОБНОВЛЕНИЕ СНОВА: Я разработал свою собственную функцию 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;
}

Вы, ребята, здесь очень помогли мне найти свой путь. Спасибо всем. 🙂

4

Решение

Вы переполненный long long так как последние два действительных значения num.value а также reversenum.value 7197630720180367016 и 6107630810270367917, которые, сложенные вместе, намного превышают максимальный размер long long (9223372036854775807 на моей машине). Это даст отрицательное значение и испортит ваш следующий звонок stoll

std :: out_of_range генерируется, если преобразованное значение выпадает из диапазона типа результата или если основная функция (std :: strtol или std :: strtoll) устанавливает errno в значение ERANGE.

(ссылка)

  • Если вы пытаетесь получить следующий маленький палиндром, Вы должны использовать другой подход, как тот, Я объяснил здесь.

Вы можете найти Живой пример Вот

  • Если вы предпочитаете / должны продолжить свой подход, вы должны либо добавить сложение вручную в строках, либо использовать BIGINT библиотека (снова взгляните на Вот и изменить plusOne() функция по своему вкусу)
2

Другие решения

От http://www.cplusplus.com/reference/string/stoll/

Если прочитанное значение выходит за пределы диапазона представимых значений long long, генерируется исключение out_of_range.

Тип данных ll не может обрабатывать длину строки. Мой отладчик сообщает мне 196 перерывов в стоимости
std::stoll (__str=\"9605805010994805921-\", __idx=0x0, __base=10)

Длинный длинный слишком мал.

Возможно, вы захотите сделать сложение для самих строк, не прибегая к числовому типу.

1

По вопросам рекламы [email protected]