#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <limits>
#include <exception>
const int PRECISION = 100;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<PRECISION> > arbFloat;
// Prototypes
bool isStringValid(const std::string & str);
bool isNumberValid(const arbFloat & x);
inline std::string resizeArbtoString(const arbFloat & x);
int main(){
arbFloat zeta = 0.0;
std::cout << "\u03b6(s), s = ";
std::string inputStr;
std::getline(std::cin, inputStr);
if(!isStringValid(inputStr)) return 2;
arbFloat input = static_cast<arbFloat>(inputStr);
if(!isNumberValid(input)) return 3;
std::cout << std::setprecision(PRECISION);
int i = 1;
if(input == 0) {
zeta = -0.5;
} else {
std::string preComp, postComp;
std::cout << "Convergence:\n";
do {
preComp = resizeArbtoString(zeta);
zeta += pow(i, -input);
postComp = resizeArbtoString(zeta);
std::cout << '\t' + preComp + '\n';
i++;
} while(preComp != postComp);
}
std::cout << "\n\u03b6(" + inputStr + ") = " << zeta << "\nAfter " << i << " iterations";
return 0;
}
// Check input
bool isStringValid(const std::string & str){
// Check if string contains spaces
if(std::count(str.begin(), str.end(), ' ') > 0){
std::cout << "\nError: Input contains spaces\n";
return false;
}
// Check if string contains multiple .
if(std::count(str.begin(), str.end(), '.') > 1){
std::cout << "\nError: Input contains multiple decimal marks\n";
return false;
}
// Check if NaN or Out of bounds (due to parsing failure)
try{
boost::lexical_cast<arbFloat>(str);
} catch(std::runtime_error){
std::cout << "\nError: Unable to parse (value too large or incorrect number type)\n";
return false;
} catch(...){
std::cout << "\nError: Input is NaN\n";
return false;
}
// Check if intentional NaN
if(boost::icontains(str, "nan")){
std::cout << "\nError: Intentional NaN\n";
return false;
}
return true;
}
// Check number
bool isNumberValid(const arbFloat & x){
// Range check
if(x == std::numeric_limits<arbFloat>::infinity()){
std::cout << "\nError: Out of bounds\n";
return false;
}
if(x == 1){
std::cout << "\nError: Complex Infinity\n";
return false;
}
if(x < 2){
std::cout << "\nError: Does not converge (unsupported)\n";
return false;
}
return true;
}
inline std::string resizeArbtoString(const arbFloat & x){
std::string resizedStr = static_cast<std::string>(x);
resizedStr.resize(PRECISION + 2);
return resizedStr;
}