5

I have this code in C++:

#include <iostream>
#include <iomanip>
#include <limits>

#include <boost/multiprecision/mpfr.hpp>
using namespace boost::multiprecision;
template<int bity>
auto obliczenie() {
    using real = number<mpfr_float_backend<bity>>;
    int cyfry = std::numeric_limits<real>::digits10;
    std::cout << std::setprecision(cyfry + 2);

    real x = 77617;
    real y = 33096;
    real wynik = real(333.75)*pow(y,6) + pow(x,2)*(real(11)*pow(x,2)*pow(y,2) - pow(y,6) -
        real(121)*pow(y,4) -real(2)) + real(5.5)*pow(y,8) + x/(real(2)*y);


    return wynik;
}
int main() {

    std::cout << "Wynik dla float: " << obliczenie<24>();
    std::cout << "\nWynik dla double: "<< obliczenie<53>();
    std::cout << "\nWynik dla long double: " << obliczenie<64>();
    std::cout << "\nWynik dla float 128: " << obliczenie<113>();
    return 0;
}

and it gives me way more precise solutions to this function than my Python script:

import mpmath
def funkcja(bity):
     mpmath.mp.prec = bity
     x = mpmath.mpf(77617)
     y = mpmath.mpf(33096)
     return mpmath.mpf(333.75*pow(y,6) + pow(x,2)*(11*pow(x,2)*pow(y,2)
            - pow(y,6) - 121*pow(y,4) - 2) + 5.5*pow(y,8) + x/(2*y))
print("\nFloat: " ,funkcja(24))
print("\nDouble: ",funkcja(53))
print("\nLong double: ",funkcja(64))
print("\nFloat 128: ", funkcja(113))

The answers C++ gives me:

Wynik dla float: 1.172603940053178631858835
Wynik dla double: -0.8273960599468213681411650954798162919990331157843848187
Wynik dla long double: -0.827396059946821368141165095479816291999033115784384819917814841671
Wynik dla float 128:
-0.8273960599468213681411650954798162919990331157843848199178148416727096930142615421803239062122310853275320280396423

(-0.827... is the correct answer to this function.)

Python on the other hand:

Float:  -6.33825e+29
Double:  -1.18059162071741e+21
Long double:  576460752303423489.0
Float 128:  1.17260394005317863185883490452018

I think I gave them the same precision to work with, so I can't understand what is the problem here.

Additionally, the same answer is given by C++ with precision 24, as give by Python with precision 113.

What is the mistake that I'm making here?

1
  • 6
    What is the mistake that I'm making here? -- real wynik = ... -- This is simply divide and conquer -- You should break up that one line calculation into separate pieces, storing each piece in separate variables, so that you know exactly where the difference is. This is also the case for the Python code. Commented Nov 16 at 13:52

2 Answers 2

8

You are not using the same precision. mpmath.mp.prec = bity sets the precision in bits (see here). On the other hand, the template argument of mpfr_float_backend is the precision in terms of number of decimal digits (see here).

This explains for example why

Wynik dla float: 1.172603940053178631858835

shows 24 decimal digits (actually you do determine the number of digits via std::numeric_limits<real>::digits10, but it is unnecessary because cyfry is just bity). On the other hand

Float:  -6.33825e+29

is limited to 24 bits precision.

Sign up to request clarification or add additional context in comments.

Comments

1

The expression in python doesn't use mpmath, but lets Python calculate the argument and feeds it into an mpf.

 mpmath.mpf(333.75*pow(y,6) + ....)

Maybe use exactly the expression you used in C++, and rename some things:


real = mpmath.mpf
wynik = real(333.75)*pow(y,6) + pow(x,2)*(real(11)*pow(x,2)*pow(y,2) - pow(y,6) -
        real(121)*pow(y,4) -real(2)) + real(5.5)*pow(y,8) + x/(real(2)*y);

This will convert your program's numeric literals into mpf objects, and python will use its magic methods __rmul__, __add__, ... instead of the python ones.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.