Jonathan Basile
Jonathan Basile

Reputation: 679

working with boost multiprecision/mpfr float - string could not be interpreted as valid integer error

I have written a program which performs some simple arithmetic with very large numbers. I succeeded in using mpz_int and mpf_float from the boost multiprecision libraries, but found that i needed more precision to achieve my purpose. I have been trying to use the mpfr library to define a float with greater precision. I was able to get my code to compile but now receive the runtime error libc++abi.dylib: terminating with uncaught exception of type boost::exception_detail::clone_impl >: The string “1572…[4000 digits]…00.328” could not be interpreted as a valid integer.

I have a feeling that it is my attempt to convert the mpfr_float I created to an integer that is causing the problem. I initialize the float from a string which is an integer, and do some division before attempting to round down and convert to an integer. Here is my typedef:

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

my declaration:

bloatfloat seed(“4716…etc.”);

and my attempted conversion:

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

If someone could help me just to accomplish this conversion and avoid the runtime error, I would be very grateful. I think though that the source of my confusion may lie deeper than that, so I’d like to explain a little about my project, and see if anyone can tell me if there is anything I am doing which is more fundamentally wrong.

I am trying to create pages of text which appear random but are constructed out of a predictable pseudo-random function. So that if someone inputs 1, then 2, then 3, they would notice no pattern between the three pages of text, but entering any of those numbers gives the same text each time. I am trying to create all possibilities of a page of 29 characters 3200 times, or 29^3200 possibilities (about 10^4680).

I am using a halton sequence to generate the pseudo-random quality, and multiplying the result by 29^3200.

Here is my halton sequence:

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

I then do a base conversion from the resulting number to base-29 to get a page of text. Initially I used mpz_int for 29^3200 (initialized from a string) - but I found that this would produce repeating patterns. depending on what the denominator from the halton sequence was. for example, input which produced the denominator 243 would produce a page of text with the same 162 characters repeating from 3200 characters, just in a different position.

Here is the base conversion segment of my program:

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";

I don’t have a good enough sense of the mathematics to understand why this repetition happened, but on a hunch I changed to a float. I found that this did much better - the patterns were much shorter and would only begin to appear at the beginning of the output string (representing the higher values), but ultimately they were still there and recognizable. I found that mpf_float worked better than mpf_float_1000, and both of them were much better than mpz_int in terms of producing more random-seeming results.

As i mentioned before, my surface question is simply: how do i avoid this runtime error? But my deeper concern is: a) why are these patterns appearing? am i correct that floats with greater precision will eliminate these repeating strings? and b) if so, is mpfr_float the best data type? what degree of precision should i give it? c) if not, what data type should i use?

I am very thankful to anyone who can answer any of these questions.

---EDIT---

I solved the problem I was having simply by sticking with mpf_float, using 29^3280 as a seed, and cutting off the last 80 characters, which were the repetitious ones. I'm still curious about fixed and variable precision, though. When I tried to define a fixed precision gmp_float with a higher template parameter I got much worse results. What exactly is fixed and variable precision and why does it produce such results?

Upvotes: 1

Views: 1055

Answers (1)

sehe
sehe

Reputation: 393064

If you want rounding, specify rounding:

seed = floor(seed); // round down

Live On 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;
}

Prints

72120170198291938481691944462909460215767645100917849314569769903319879910079512946106525240277237710021170290767957328848646950935465029226151498308985758562688914829917251602698913104124976338790039364917184704719917620831932377742375478729989990245302165516965096197650978241164946505185887844682359841650913695092211842658961888955929451122376637902571040334250132354349810145543962289743784415526958699304982112342414708539054982375571267291747685016505910754910093667630742418856403647152637034131136314751316526708109882084256836486710846745814714821506663162052144272381184029624965369290721727319414295446747272347928112685341984635121458991945868515415195171928184132281283391670402306280654720514638821877493881271599571277364984644114752231471655539342153193201013

Upvotes: 1

Related Questions