Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Общие вопросы > Библиотека для работы с длинными числами (BigInteger)


Автор: Jin X 29.07.18, 21:52
Всех приветствую!

Ищу библиотеку для работы с длинными целыми (длинные вещественные и комплексные числа особо не интересуют, но если будет в комплекте, будет только плюсом).
Такие большие библиотеки, как GMP (особенно которые тащат за собой DLL) не нужны, надо что-то попроще, но быстрое и функциональное.

Есть отличная (очень быстрая и функциональная) библиотека для Delphi: http://www.rvelthuis.de/programs/bigintegers.html
Хотелось бы найти что-то такое же для C++ (скажем, одну или несколько связок из файлов h+cpp).

Нашёл вот это: https://sourceforge.net/projects/cpp-bigint/
Не такая шустрая, конечно, вещь, как хотелось бы, но всё равно более или менее. Но со странностями (например, реализован оператор +=, но не реализован *= ; можно умножать на int, но при делении нужно вызывать BigInt::Rossi(int)).

p.s. Ещё находил вот это: https://github.com/maemual/BigInt – вещь вообще простая, не самая быстрая, но с багами (как минимум при делении, как я понял). Не годится.

Автор: Qraizer 29.07.18, 22:31
Ну думаю, что подойдёт, судя по характеристикам запроса, однако не могу не упомянуть boost::multiprecision. Для плавающей точки можно сразу быстрый пример, ибо уже есть готовый:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <iostream>
    #include <iterator>
    #include <vector>
    #include <algorithm>
    #include <iomanip>
    #include <boost/multiprecision/cpp_bin_float.hpp>
     
    #include <chrono>
    #include <cmath>
    #include <typeinfo>
     
    // вывод времени в микросекундах
    template <typename Ch, typename Tr>
    std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os,
                                           std::chrono::high_resolution_clock::duration time)
    {
      return os << std::chrono::duration_cast<std::chrono::microseconds>(time).count();
    }
     
    // точная тестовая  функция
    template <typename T>
    T func(T x)
    {
      return pow(x-5, 6);
    }
     
    // тестовая функция с потерей точности
    template <typename T>
    T poly(T x)
    {
      return pow(x, 6) - 30 * pow(x, 5) + 375 * pow(x, 4) - 2500 * pow(x, 3) + 9375 * pow(x, 2) - 18750 * x + 15625;
    }
     
    // запуск тестовой функции на критическом интервале с малым шагом
    template <typename T, T Fn(T), typename It>
    void run(It it)
    {
      const T start = static_cast<T>(4.98),
              end   = static_cast<T>(5.02),
              step  = static_cast<T>(0.0001);
     
      for (T f = start; f < end; f += step)
        *it++ = Fn(f);
    }
     
    // запуск теста COUNT раз с замером времени
    template <typename T, T Fn(T), typename Cont>
    void test(Cont &cont)
    {
      std::cerr << typeid(T).name() << ":\n";
     
      const int COUNT = 100;
      auto      start = std::chrono::high_resolution_clock::now();
     
      for (int i = 0; i < COUNT; ++i)
      {
        cont.clear();
        run<T, Fn>(std::back_inserter<Cont>(cont));
      }
     
      auto      diff  = std::chrono::high_resolution_clock::now() - start;
      std::cerr << diff << " mcs" << std::endl;
    }
     
    // тестирование обоих тестовых функций с выводом их результатов
    template <typename T> void boost_test()
    {
      std::vector<T> vT_1;
      std::vector<T> vT_2;
     
      test<T, func>(vT_1);
      test<T, poly>(vT_2);
     
      for (int i = 0; i < std::min(vT_1.size(), vT_2.size()); ++i)
        std::cout << i << ":\t" << std::setw(20) << vT_1[i] << '\t'
                                << std::setw(20) << vT_2[i] << '\n';
      std::cout << std::endl;
    }
     
    int main()
    {
      using namespace boost::multiprecision;
     
      typedef number<cpp_bin_float<50,  digit_base_10>> cpp_dec_50;
      typedef number<cpp_bin_float<1000, digit_base_2>> cpp_bin_float_1000;
     
      boost_test<cpp_bin_float_double>();// IEEE's double precision
      boost_test<cpp_bin_float_quad>();  // IEEE's quad precision
      boost_test<cpp_dec_50>();          // 50-dec
      boost_test<cpp_bin_float_1000>();  // 1000-bit
    }
Ну как быстрый... тут сразу несколько в одном: фактор увеличения точности с ростом битности мантиссы, время заполнения массивов каждой точности и лёгкая адаптация для других условий тестирования.
Для целочисленной арифметики тоже есть подобные шаблоны. Комплексные легко подхватываются std::complex. Может работать с готовыми фреймворками GMP, libtommath, libquadmath и/или MPFR, если их нет, имеет свои классы. Но есть минус: это буст.

Автор: Jin X 30.07.18, 17:42
Цитата Qraizer @
Но есть минус: это буст.
А что не так с бюстом? :)

Автор: ЫукпШ 31.07.18, 17:53
Цитата Jin X @
Есть отличная (очень быстрая и функциональная) библиотека для Delphi: http://www.rvelthuis.de/programs/bigintegers.html
Хотелось бы найти что-то такое же для C++ (скажем, одну или несколько связок из файлов h+cpp).

Если не найдёшь, то можно на её основе сделать dll.
И используй дальше, как хочешь.

Автор: Jin X 01.08.18, 14:49
ЫукпШ, не хочу DLL.
Тут люди MPIR предлагают. Она без DLL идёт и перегружено там всё нормально...

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)