英文:
How to catch boost::wrapexcept from cpp_int?
问题
For some reason there was a change of behavior between boost 1.78 and 1.79 causing now cpp_int convert_to<double>
conversion throwing exceptions for very big numbers. Sometimes it is overflow_error, sometimes domain_error.
I have not found if it is intentional change or not, but right now as a quick first step I would like just to react on this and preserve the old behavior of our code, which was giving infinity for such numbers, std::numeric_limits<double>::max
.
But I have trouble catching the exception. How can I catch instance of boost::wrapexcept<std::overflow_error>
? Is some special handling required? Following simple code - see behavior comparison boost 78 vs 79 here - is not catching the exception but just terminates with
terminate called after throwing an instance of 'boost::wrapexceptstd::overflow_error'
what(): Error in function float_next
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
boost::multiprecision::cpp_int number(strNumber);
try {
std::cout << number.convert_to<double>() << "\n";
} catch (boost::wrapexcept<std::overflow_error> &e) {
std::cout << "boost exception caught" << "\n";
} catch (...) {
std::cout << "some exception caught" << "\n";
}
std::cout << "finished" << "\n";
}
I am expecting at least "some exception caught" line to be called, but it is not. Thanks for help.
Note after reading some answers:
The code is just an example. My current concern is not to convert the number to double. That is another following issue. More important for me right now is actually to catch the exception somehow so that I can return std::numeric_limits<double>::max()
instead of exception, and the existing program will work the same way as with older boost (breaking change concerns).
Note 2: This seems to be a bug in boost, caused by throwing an exception in noexcept method. That terminates the program without the possibility to catch the exception. Thanks @Ext3h for help. I reported the thing in boost and will properly answer and close this issue if confirmed.
英文:
For some reason there was a change of behavior between boost 1.78 and 1.79 causing now cpp_int convert_to<double>
conversion throwing exceptions for very big numbers. Sometimes it is overflow_error, sometimes domain_error.
I have not found if it is intentional change or not, but right now as a quick first step I would like just to react on this and preserve the old behavior of our code, which was giving infinity for such numbers, std::numeric_limits<double>::max
.
But I have trouble catching the exception. How can I catch instance of boost::wrapexcept<std::overflow_error>
? Is some special handling required? Following simple code - see behavior comparison boost 78 vs 79 here - is not catching the exception but just terminates with
terminate called after throwing an instance of 'boost::wrapexcept<std::overflow_error>'
what(): Error in function float_next<double>(double): Overflow Error
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
boost::multiprecision::cpp_int number(strNumber);
try {
std::cout << number.convert_to<double>() << "\n";
} catch (boost::wrapexcept<std::overflow_error> &e) {
std::cout << "boost exception caught" << "\n";
} catch (...) {
std::cout << "some exception caught" << "\n";
}
std::cout << "finished" << "\n";
}
I am expecting at least "some exception caught" line to be called, but it is not. Thanks for help.
Note after reading some answers:
The code is just an example. My current concern is not to convert the number to double. That is another following issue. More important for me right now is actually to catch the exception somehow so that I can return std::numeric_limits<double>::max()
instead of exception and the existing program will work the same way as with older boost (breaking change concerns).
Note 2: This seems to be a bug in boost, caused by throwing an exception in noexcept method. That terminates the program without possibility to catch the exception. Thanks @Ext3h for help. I reported the thing in boost and will properly answer and close this issue if confirmed.
答案1
得分: 1
不要尝试捕获包装器 - 它继承自 std::overflow_error
,这是你应该捕获的异常。
还要确保以 const std::overflow_error&
的方式捕获异常 - 如果你尝试捕获异常为其他类型,可能会导致一系列意外的副作用。具体来说,编译器将不得不为你的异常处理程序复制异常,这可能会因各种原因而失败或导致效率低下的行为。
最后,你仍然遇到的问题可能是这一行 boost::multiprecision::cpp_int number(strNumber);
已经在抛出异常。
检查异常规范:https://www.boost.org/doc/libs/1_80_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html
英文:
Don't try to catch the wrapper - it's inheriting from std::overflow_error
and that's what you should go and catch.
Also make sure you are catching the exception as const std::overflow_error&
- your are running into a whole series of unexpected side effects if you ever try to catch an exception as anything other than a const reference. Namely, the compiler will have to copy the exception just for your exception handler, which may fail or lead to inefficient behavior for various reasons.
Finally, the issue you are still having is that the line boost::multiprecision::cpp_int number(strNumber);
is potentially already throwing an exception.
Check the exception specification: https://www.boost.org/doc/libs/1_80_0/libs/multiprecision/doc/html/boost_multiprecision/tut/ints/cpp_int.html
答案2
得分: 0
To avoid try catch don't use convert_to
like you did and instead of do this Boost Multiprecision float, Constructing and Interconverting Between Number Types:
不要使用convert_to
来避免try catch,而是像这样做 Boost Multiprecision float, 构造和在数字类型之间进行相互转换:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace mp = boost::multiprecision;
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
mp::cpp_int number(strNumber);
std::cout << "Boost Multiprecision: "
<< std::setprecision(std::numeric_limits<mp::cpp_dec_float_50>::digits10)
<< number << std::endl;
std::cout << "Double: "
<< std::setprecision(std::numeric_limits<double>::digits10)
<< number << std::endl;
}
Output:
输出:
Boost Multiprecision: 179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
Double: 179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
Like that you don't need try catch.
这样你就不需要try catch。
Or you can How to convert from boost::multiprecision::cpp_int to cpp_dec_float<0>:
或者你可以 如何从boost::multiprecision::cpp_int转换为cpp_dec_float<0>:
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
int main() {
using Int = mp::cpp_int;
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
Int number(strNumber);
using Dec = mp::number<mp::cpp_dec_float<0>>;
std::cout << number.convert_to<Dec>();
}
Output:
输出:
1.79769e+308
Or if you need try catch do the next thing:
或者如果你需要try catch,可以做如下操作:
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
boost::multiprecision::cpp_int number(strNumber);
try {
std::cout << number.convert_to<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<0>>() << "\n";
} catch (boost::wrapexcept<std::overflow_error> const& e) {
std::cout << "boost exception caught" << "\n";
} catch (...) {
std::cout << "some exception caught" << "\n";
}
std::cout << "finished" << "\n";
}
Output:
输出:
1.79769e+308
finished
英文:
To avoid try catch don't use convert_to
like you did and instead of do this Boost Multiprecision float, Constructing and Interconverting Between Number Types:
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace mp = boost::multiprecision;
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
mp::cpp_int number(strNumber);
std::cout << "Boost Multiprecision: "
<< std::setprecision(std::numeric_limits<mp::cpp_dec_float_50>::digits10)
<< number << std::endl;
std::cout << "Double: "
<< std::setprecision(std::numeric_limits<double>::digits10)
<< number << std::endl;
}
Output:
Boost Multiprecision: 179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
Double: 179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625
Like that you don't need try catch.
Or you can How to convert from boost::multiprecision::cpp_int to cpp_dec_float<0>:
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
int main() {
using Int = mp::cpp_int;
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
Int number(strNumber);
using Dec = mp::number<mp::cpp_dec_float<0>>;
std::cout << number.convert_to<Dec>();
}
Output:
1.79769e+308
Or if you need try catch do the next thing:
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
int main() {
std::string strNumber = "179769313486231590617005494896502488139538923424507473845653439431848569886227202866765261632299351819569917639009010788373365912036255753178371299382143631760131695224907130882552454362167933328609537509415576609030163673758148226168953269623548572115351901405836315903312675793605327103910016259918212890625";
boost::multiprecision::cpp_int number(strNumber);
try {
std::cout << number.convert_to<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<0>>>() << "\n";
} catch (boost::wrapexcept<std::overflow_error> const& e) {
std::cout << "boost exception caught" << "\n";
} catch (...) {
std::cout << "some exception caught" << "\n";
}
std::cout << "finished" << "\n";
}
Output:
1.79769e+308
finished
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论