pythonc++precisionmpmath

Why are C++ and Python giving me different answers, when given (I think) the same precision?


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?


Solution

  • 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.