Я написал программу, которая выполняет простую арифметику с очень большими числами. Мне удалось использовать mpz_int и mpf_float из библиотек boost multiprecision, но я обнаружил, что мне нужно больше точности для достижения моей цели. Я пытался использовать библиотеку mpfr, чтобы определить float с большей точностью. Я смог получить свой код для компиляции, но теперь получаю ошибку времени выполнения libc ++ abi.dylib: завершение с необработанным исключением типа boost :: exception_detail :: clone_impl>: строка «1572… [4000 цифр]… 00.328» могла не следует интерпретировать как действительное целое число.
У меня такое ощущение, что это моя попытка преобразовать созданный мной mpfr_float в целое число, которое вызывает проблему. Я инициализирую 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).
Я использую последовательность Halton для генерации псевдослучайного качества и умножаю результат на 29 ^ 3200.
Вот моя последовательность Halton:
while (input>0) {
denominator *=3;
numerator = numerator * 3 + (input%3);
input = input/3;
}
Затем я делаю базовое преобразование из полученного числа в base-29, чтобы получить страницу текста. Первоначально я использовал mpz_int для 29 ^ 3200 (инициализируется из строки) — но я обнаружил, что это приведет к повторяющимся шаблонам. в зависимости от того, что знаменатель из последовательности Halton был. например, ввод, который произвел знаменатель 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 лучшим типом данных? Какую точность я должен дать? в) если нет, какой тип данных я должен использовать?
Я очень благодарен всем, кто может ответить на любой из этих вопросов.
—РЕДАКТИРОВАТЬ—
Я решил проблему, которую я имел, просто придерживаясь mpf_float, используя 29 ^ 3280 в качестве начального числа, и обрезая последние 80 символов, которые были повторяющимися. Мне все еще интересно узнать о фиксированной и переменной точности. Когда я попытался определить фиксированную точность gmp_float с более высоким параметром шаблона, я получил гораздо худшие результаты. Что именно является фиксированной и переменной точностью и почему она дает такие результаты?
Если вы хотите округлить, укажите округление:
seed = floor(seed); // round down
#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