The problem is that you are not explicitly setting the accuracy, so you get the standard accuracy, which is usually (I think) 64 bits, so the results are different in the last bit (s) due to different rounding in different calculation methods. This is approximately 20 digits of the general prefix (the difference can increase significantly with large calculations). If you set higher accuracy,
#include <gmp.h> #include <gmpxx.h> #include <iostream> #include <iomanip> int main() { mpf_class x(1.0,200), y(1.0,200), z(1.0,200), a("9.3",200), b("9.8",200), c(0,200); c = a*b; for (int i = 0; i < 15; i++) { x *= a; y *= b; z *= c; } std::cout << z << "\n" << (x*y) << std::endl; std::cout << z - x*y << std::endl; return 0; }
200 bits here, you will get a more accurate result:
$ ./a.out 2.48677e+29 2.48677e+29 -4.80637e-49
therefore, the general prefix is about 80 decimal digits or almost 256 bits (the smallest multiple of 64 is greater than 199).
With an accuracy of 2000, the difference is -2.78942e-588 with line constructors, 0 if they are initialized from double (but then, of course, the initial precision is limited to 53 bits, so that just means that both paths accumulate the error in the same way).
source share