0

Keep in mind that Precision is based on the total number of digits and not the decimal places, but I need a way to set the Decimal places and all I can find is Precision, so I am trying to work with it, so I account for the number of digits in the whole number, in order to get this to work, but that is not working.

I want to do some math and return with a set precision value, the function takes a string of a very large number with a very large decimal precision and returns it as a string set to the number of decimals passed in as precision:

 #include <boost/multiprecision/mpfr.hpp>

 QString multiply(const QString &mThis, const QString &mThat, const unsigned int &precison)
 {
    typedef boost::multiprecision::number<mpfr_float_backend<0> > my_mpfr_float;
    my_mpfr_float aThis(mThis.toStdString());
    my_mpfr_float aThat(mThat.toStdString());
    my_mpfr_float::default_precision(precison);
    my_mpfr_float ans = (aThis * aThat);
    return QString::fromStdString(ans.str());
 } 

I have tried it without the typedef, same problem;

MathWizard::multiply("123456789.123456789", "123456789.123456789", 20);

18 digits of Precision, 9 + 9, I should ask for 30

will return 22 decimal places

15241578780673678.51562

instead of 20

15241578780673678.516

So why is it off by 2?

I would like to make the precision change after the math, but it seems you have to set it before, and not like the examples that boost shows in their example, but still does not return the correct value, doing it after does not change value.

Update: Compare what I did to what they say works in this Post: how to change at runtime number precision with boost::multiprecision

 typedef number<gmp_float<0> >     mpf_float;
 mpfr_float a = 2;
 mpfr_float::default_precision(1000);
 std::cout << mpfr_float::default_precision() << std::endl;
 std::cout << sqrt(a) << std::endl; // print root-2

I have noticed differences between gmp_float, mpf_float (using boost/multiprecision/gmp.hpp) and mpfr_float, and mpfr_float will give me a closer precision, for example, if I take the number (1/137):

 mpf_float
 0.007299270072992700729927007299270072992700729927007299270073
 only 1 Precision, 23 digits when set to 13
 0.00729927007299270072993
 mpfr_float
 0.007299270072992700729929
 only 1 Precision, 16 digits when set to 13
 0.0072992700729928

With only 1 Precision I would expect my answer to be have one less decimal.

The other data types do similar, I did try them all, so this code will work the same for all the data types described here:

boost 1.69.0: multiprecision Chapter 1

I also must point out that I rely on Qt since this function is used in a QtQuick Qml Felgo App, and actually I could not figure out to convert this to string without converting it to an exponent, even though I used ans.str() for both, my guess is that fromStdString does something different then std::string(ans.str()).

I figure if I can not figure his out, I will just do String Rounding to get the correct precision.

 std::stringstream ss;
 ss.imbue(std::locale(""));
 ss << std::fixed << std::setprecision(int(precison)) << ans.str();
 qDebug() << "divide(" << mThis << "/" << mThat << " @ " << precison << " =" << QString::fromStdString(ss.str()) << ")";
 return QString::fromStdString(ss.str());

I still could not get away without using QString, but this did not work, it returns 16 digits instead of 13, I know that is a different question, as such I just post it to show my alternatives do not work any better at this point. Also note that the divide function works the same as the multiply, I used used that example to show the math has nothing to do with this, but all the samples they are showing me do not seem to work correctly, and I do not understand why, so just to make the steps clear:

  1. Create back end: typedef boost::multiprecision::number > my_mpfr_float;
  2. Set Precision: my_mpfr_float::default_precision(precision);
  3. Set initial value of variable: my_mpfr_float aThis(mThis.toStdString());
  4. Do some math if you want, return value with correct Precision.

I must be missing something.

I know I can just get the length of the string, and if longer than Precision, then check if Precision + 1 is greater than 5, if so add 1 to Precision and return a substring of 0, Precision and be done with all this Correct way of doing things, I could even do this in JavaScript after the return, and just forget about doing it the Correct way, but I still think I am just missing something, because I can not believe this is the way this is actually supposed to work.

Submitted Bug Report: https://github.com/boostorg/multiprecision/issues/127

user83395
  • 103
  • 1
  • 8
  • I was going to edit tags, but its gone, but my point was that this is in Qt using boost, and you are right, it does not make any difference, thanks for point that out, you really do know you stuff, you have a great track record, it has nothing to do with the string in fact, just the way you set the precision, which I have done, according to boost docs, so I must be missing something simple, but can not find many examples on how to use any of these multiprecision types. – user83395 Mar 31 '19 at 02:13
  • The tags serve to attract the attention of the communities that exist in SO, by using the tags qt + boost is calling the community that uses both libraries that is smaller than the community of boost and qt, instead if you use only boost the The boost community will be the one you attract. conclusion: choose your labels well and rewrite your example so that it does not depend on Qt. – eyllanesc Mar 31 '19 at 02:18
  • If I try to convert it to a string, instead of QString, it changes the answer to an exponential, and I need it as a decimal, and I can not find any examples using multiprecision conversion to string, which is part of my problem, I really do not know how to use this function completely, due to lack of examples, so I need to use Qt for this example to work correctly till I find another way to convert from multiprecision to a string, even using cout, it converts it to exponential. But I do get that I need to keep example to a bare minimum and tried. – user83395 Mar 31 '19 at 04:59
  • I updated my answer to be more specific, provide links and code, with the results of what I have found. This is a Qt Qml App, so this C++ gets returned to Qml as a string, and converting large numbers to a number hoses its accuracy if it can not handle it. I need to know if these examples really work, keep in mind that close is not an option I have in Math, I need the exact value at a fixed precision, so I need these examples to work, because if they do, all I am doing is what they tell me to do, so why does my code fail? – user83395 Mar 31 '19 at 21:00

0 Answers0