У меня есть реализация с фиксированной запятой для какого-то финансового приложения. В основном это целое число, заключенное в класс, который основан на количестве десятичных знаков, заданных N
, которые рассматриваются как десятичное число. Класс параноидален и проверяет наличие переполнений, но когда я запустил свои тесты в режиме выпуска, и они потерпели неудачу, и, наконец, я создал этот минимальный пример, который демонстрирует проблему:
#include <iostream>
#include <sstream>
template <typename T, typename U>
typename std::enable_if<std::is_convertible<U, std::string>::value, T>::type
FromString(U&& str)
{
std::stringstream ss;
ss << str;
T ret;
ss >> ret;
return ret;
}
int main()
{
int NewAccu=32;
int N=10;
using T = int64_t;
T l = 10;
T r = FromString<T>("1" + std::string(NewAccu - N, '0'));
if (l == 0 || r == 0) {
return 0;
}
T res = l * r;
std::cout << l << std::endl;
std::cout << r << std::endl;
std::cout << res << std::endl;
std::cout << (res / l) << std::endl;
std::cout << std::endl;
if ((res / l) != r) {
throw std::runtime_error(
"FixedPoint Multiplication Overflow while upscaling [:" + std::to_string(l) + ", " + std::to_string(r) + "]");
}
return 0;
}
Это происходит с Clang 6, моя версия:
$ clang++ --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Это забавно, потому что это впечатляющая оптимизация, но это разрушает мое приложение и мешает мне обнаружить переполнения. Я смог воспроизвести эту проблему в g ++ здесь . Там не исключение.
Обратите внимание, что исключение выдается в режиме отладки, но не в режиме выпуска.