работа с boost multiprecision/mpfr float - строка не может быть интерпретирована как действительная целочисленная ошибка

Я написал программу, которая выполняет простые арифметические действия с очень большими числами. Мне удалось использовать mpz_int и mpf_float из библиотек повышения точности, но я обнаружил, что мне нужно больше точности для достижения моей цели. Я пытался использовать библиотеку mpfr для определения поплавка с большей точностью. Я смог скомпилировать свой код, но теперь получаю ошибку времени выполнения libc++abi.dylib: завершение с необработанным исключением типа boost::exception_detail::clone_impl >: Строка «1572…[4000 цифр]…00.328» может не интерпретируется как допустимое целое число.

У меня такое ощущение, что это моя попытка преобразовать mpfr_float, который я создал, в целое число, которое вызывает проблему. Я инициализирую число с плавающей запятой из строки, которая является целым числом, и делаю некоторое деление, прежде чем пытаться округлить и преобразовать в целое число. Вот мой typedef:

typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<4680> > bloatfloat;

моя декларация:

bloatfloat seed(“4716…etc.”);

и моя попытка преобразования:

boost::multiprecision::mpz_int seedint = seed.convert_to<boost::multiprecision::mpz_int>();

Если бы кто-то мог помочь мне просто выполнить это преобразование и избежать ошибки времени выполнения, я был бы очень благодарен. Однако я думаю, что источник моего замешательства может лежать глубже, поэтому я хотел бы немного объяснить о своем проекте и посмотреть, может ли кто-нибудь сказать мне, есть ли что-то, что я делаю, что является более фундаментально неправильным.

Я пытаюсь создать страницы текста, которые кажутся случайными, но построены из предсказуемой псевдослучайной функции. Таким образом, если кто-то введет 1, затем 2, затем 3, он не заметит никакой закономерности между тремя страницами текста, но ввод любого из этих чисел каждый раз дает один и тот же текст. Я пытаюсь создать все возможности страницы из 29 символов 3200 раз или 29 ^ 3200 возможностей (около 10 ^ 4680).

Я использую последовательность Холтона для создания псевдослучайного качества и умножаю результат на 29^3200.

Вот моя последовательность Халтона:

while (input>0) {
    denominator *=3;
    numerator = numerator * 3 + (input%3);
    input = input/3;
}

Затем я выполняю базовое преобразование полученного числа в основание 29, чтобы получить страницу текста. Первоначально я использовал mpz_int для 29 ^ 3200 (инициализирован из строки), но обнаружил, что это приведет к повторяющимся шаблонам. в зависимости от того, каков был знаменатель последовательности Холтона. например, ввод, который произвел знаменатель 243, даст страницу текста с теми же 162 символами, повторяющимися из 3200 символов, только в другом месте.

Вот базовый конверсионный сегмент моей программы:

boost::multiprecision::mpz_int seedint(seed); //converts from mpf_float
boost::multiprecision::mpz_int holder = 0;
std::string permuda [29] = {" ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ",", "."};
std::string book = "";
holder = seedint%29;
int conversion = holder.convert_to<int>();
book = permuda[conversion];
while (seedint>=29) {
    seedint = seedint/29;
    holder = seedint%29;
    conversion = holder.convert_to<int>();
    book.insert(0,permuda[conversion]);
}
std::cout << book << "\n";

У меня недостаточно хорошее понимание математики, чтобы понять, почему произошло это повторение, но по наитию я превратился в поплавок. Я обнаружил, что это работает намного лучше - шаблоны были намного короче и начинали появляться только в начале выходной строки (представляя более высокие значения), но в конечном итоге они все еще были там и узнаваемы. Я обнаружил, что mpf_float работает лучше, чем mpf_float_1000, и оба они намного лучше, чем mpz_int, с точки зрения получения более случайных результатов.

Как я упоминал ранее, мой поверхностный вопрос прост: как мне избежать этой ошибки во время выполнения? Но меня более глубоко беспокоит: а) почему появляются эти паттерны? Я прав, что поплавки с большей точностью устранят эти повторяющиеся строки? и б) если да, то является ли mpfr_float лучшим типом данных? какую степень точности я должен дать ему? c) если нет, то какой тип данных я должен использовать?

Я очень благодарен всем, кто может ответить на любой из этих вопросов.

---РЕДАКТИРОВАТЬ---

Я решил проблему, которая у меня была, просто придерживаясь mpf_float, используя 29 ^ 3280 в качестве семени и отрезая последние 80 символов, которые были повторяющимися. Однако мне все еще интересно узнать о фиксированной и переменной точности. Когда я попытался определить фиксированную точность gmp_float с более высоким параметром шаблона, я получил гораздо худшие результаты. Что такое фиксированная и переменная точность и почему она дает такие результаты?


person Jonathan Basile    schedule 09.04.2015    source источник
comment
Кажется, здесь присутствует умеренная степень проблемы X/Y. В одном дополнительном предложении мы можем понять, что вы пытаетесь сгенерировать уникальные индексы в огромной целочисленной области, используя псевдослучайную вещь серии Халтона. Возможно, вы бы предпочли задать вопрос об этом :)   -  person sehe    schedule 10.04.2015
comment
Рассматривали ли вы рациональные типы?   -  person sehe    schedule 10.04.2015
comment
Что ж, я попытался дать описание предыстории моего проекта, чтобы сделать все возможное, чтобы избежать проблемы XY — как вы думаете, я бы потерял меньше данных, если бы работал с рациональными числами, а не с целыми числами или числами с плавающей запятой? Я все еще пытаюсь понять фиксированную и переменную точность и то, как они влияют на результаты, которые я получаю.   -  person Jonathan Basile    schedule 10.04.2015
comment
Ну, в таком виде вся ссылка на сериал Халтона совершенно неуместна. Я также не чувствую, что использование рациональных чисел уменьшит потребление памяти, пока мы не узнаем, чего вы пытаетесь достичь. FWIW - это запах дизайна, если вам нужно вырезать большие куски результата, чтобы сделать вещи достаточно случайными. Что-то подсказывает мне, что подход не подходит для решения проблемы или его применение ошибочно. Но вопрос не в этом... :)   -  person sehe    schedule 10.04.2015


Ответы (1)


Если вы хотите округлить, укажите округление:

seed = floor(seed); // round down

Жить на Coliru

#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/mpfr.hpp>
#include <iostream>

namespace bmp = boost::multiprecision;

int main() {

    typedef bmp::number<bmp::mpfr_float_backend<4680> > bloatfloat;

    bloatfloat seed(
            "721201701982919384816919444629094602157676451009178493145697699033198799100795129"
            "461065252402772377100211702907679573288486469509354650292261514983089857585626889"
            "148299172516026989131041249763387900393649171847047199176208319323777423754787299"
            "899902453021655169650961976509782411649465051858878446823598416509136950922118426"
            "589618889559294511223766379025710403342501323543498101455439622897437844155269586"
            "993049821123424147085390549823755712672917476850165059107549100936676307424188564"
            "036471526370341311363147513165267081098820842568364867108467458147148215066631620"
            "521442723811840296249653692907217273194142954467472723479281126853419846351214589"
            "919458685154151951719281841322812833916704023062806547205146388218774938812715995"
            "71277364984644114752231471655539342153193201013.261");

    seed = floor(seed); // round down
    auto seedint = seed.convert_to<bmp::mpz_int>();

    std::cout << seedint;
}

Отпечатки

72120170198291938481691944462909460215767645100917849314569769903319879910079512946106525240277237710021170290767957328848646950935465029226151498308985758562688914829917251602698913104124976338790039364917184704719917620831932377742375478729989990245302165516965096197650978241164946505185887844682359841650913695092211842658961888955929451122376637902571040334250132354349810145543962289743784415526958699304982112342414708539054982375571267291747685016505910754910093667630742418856403647152637034131136314751316526708109882084256836486710846745814714821506663162052144272381184029624965369290721727319414295446747272347928112685341984635121458991945868515415195171928184132281283391670402306280654720514638821877493881271599571277364984644114752231471655539342153193201013

person sehe    schedule 09.04.2015