2015-09-27 3 views
4

Я являюсь абсолютным новичком в C++. Буквально. Прошло всего неделю. Сегодня я писал программу для проверки того, сколько итераций необходимо сделать, чтобы сделать определенное число палиндромным. Вот код:std :: _ throw_out_of_range происходит из ниоткуда

#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 я получаю сообщение об ошибке. Он говорит:

Terminate вызывается после метания экземпляра 'станд :: out_of_range' , что(): Stoll

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

UPDATE: На этот раз я попытался сделать это с помощью библиотеки ttmath. Но arghs! Он снова останавливается в 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 может быть 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. :)

UPDATE AGAIN: Я разработал собственную функцию 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; 
} 

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

+2

Сомневаюсь, что это происходит от «никуда». Вы даже подумали о том, чтобы прочитать документацию для 'stoll'? Это сразу объясняло бы проблему. –

ответ

2

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

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

(reference)

  • Если вы пытаетесь получить следующий наименьший палиндром, вы должны использовать другой подход, как одной I explained here.

Вы можете найти Live Example здесь

  • Если вы хотите/должны продолжать с вашим подходом вы должны либо сделать добавление вручную на струнах или использовать BigInt библиотеку (снова взять посмотрите на here и изменить функцию plusOne() по своему вкусу)
+0

Итак, следует ли вместо этого использовать переменную UInt из ttmath? – SinTan1729

+0

@SayantanSantra Я добавил полное объяснение в случае, если вы пытаетесь найти следующий маленький палиндром с номером ввода 'N', плюс резервное решение, если вы предпочитаете продолжать свой подход. Если 'UInt' означает' unsigned integer', это не поможет. Взгляните на [диапазон значений] (http://en.cppreference.com/w/cpp/language/types) здесь. Использование 'unsigned long long' может помочь вам преодолеть это значение, но я предлагаю использовать другой подход, как я объяснил. –

+0

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

1

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

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

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

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

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

+0

Итак, следует ли вместо этого использовать переменную UInt из ttmath? – SinTan1729

 Смежные вопросы

  • Нет связанных вопросов^_^