Is this a bug in mpf_class types? - overloading

I came across a strange thing today while playing with the higher precision mpf_class of data type: it seems that any pre-multiplication, more than once, of a complex <mpf_class> object by an mpf_class type is problematic, but single pre-multiplication is fine, as is post-multiplication of these objects by several mpf_class objects:
#include <stlib.h>
#include <complex>
#include <gmpxx.h>
typedef mpf_class my_float;
const my_float two("2.0",150); //150 bit prec float
int main( int argc , char **argv )
{
mpf_set_default_prec(150); //default prec in bits
complex<my_float> q1(my_float("5.268E-10"),my_float("8.789541E2"));
complex<my_float> q2=two*q1; //no problems
complex<my_float> q3=q1*two; //no problems
complex<my_float> q3b=two*two*two; //no problems
complex<my_float> q4=two*q1*two; //no problems
complex<my_float> q5=q1*two*two; //no problems
//complex<my_float> q6=two*two*q1; //!doesn't like!
//complex<my_float> q7=(two*two)*q1; //!doesn't like!
complex<my_float> q8=-two*q1; //!doesn't like!
return 0;
}
It seem if you pre-multiply a complex of these mpf_class objects more than once you are in trouble. Yet post-multiplication is fine numerous times. Similarly multiplying the mpf_class objects between themselves is also fine as many times as you like.
What is going on here?

std::complex< T > shows well defined behaviour only for T = float, double, or long double. If you use other types the behaviour is undefined.

Related

C++ float vs double cout setprecision oddities(newbie)

Can anyone explain why these two variable of the same value can output different values when i use setprecision()?
#include <iostream>
#include <iomanip>
int main()
{
float a=98.765;
double b = 98.765;
//std::cout<<std::setprecision(2)<<a<<std::endl;
std::cout<<std::fixed;
std::cout<<std::setprecision(2)<<a<<std::endl;
std::cout<<std::setprecision(2)<<b<<std::endl;
}
The output for a will be 98.76 while the output for b will be 98.77.
Those variables don't have the same value. When you shoehorn the literal double of 98.765 into the float, it has to do a best fit, and some precision is lost.
You can see this quite easily if you change the precision to 50, you'll also see that not even the double can represent that value exactly:
98.76499938964843750000000000000000000000000000000000
98.76500000000000056843418860808014869689941406250000
However, the important thing is that the former float variable will round down, the latter double will round up.
See also the IEEE754 online converter.

const vs #define (strange behavior)

I used to replace const with #define, but in the below example it prints false.
#include <iostream>
#define x 3e+38
using namespace std;
int main() {
float p = x;
if (p==x)
cout<<"true"<<endl;
else
cout<<"false"<<endl;
return 0;
}
But if I replace
#define x 3e+38
with
const float x = 3e+38;
it works perfectly, question is why? (I know there are several topics discussed for #define vs const, but really didn't get this, kindly enlighten me)
In c++ the literals are double precision. In the first examples the number 3e+38 is first converted to float in the variable initialization and then back to double precision in the comparison. The conversions are not necessary exact, so the numbers may differ. In the second example numbers stay float all the time. To fix it you can change p to double, write
#define x 3e+38f
(which defines a float literal), or change the comparison to
if (p == static_cast<float>(x))
which performs the same conversion as the variable initialization, and does then the comparison in single precision.
Also as commented the comparison of floating point numbers with == is not usually a good idea, as rounding errors yield unexpected results, e.g., x*y might be different from y*x.
The number 3e+38 is double due its magnitude.
The assignment
float p = x;
causes the 3e+38 to lose its precision and hence its value when stored in p.
thats why the comparison :
if(p==x)
results in false because p has different value than 3e+38.

Floating point computation changes if stored in intermediate "double" variable

I am trying to write a simple log base 2 method. I understand that representing something like std::log(8.0) and std::log(2.0) on a computer is difficult. I also understand std::log(8.0) / std::log(2.0) may result in a value very slightly lower than 3.0. What I do not understand is why putting the result of a the calculation below into a double and making it an lvalue then casting it to an unsigned int would change the result compared to casting the the formula directly. The following code shows my test case which repeatedly fails on my 32 bit debian wheezy machine, but passes repeatedly on my 64 bit debian wheezy machine.
#include <cmath>
#include "assert.h"
int main () {
int n = 8;
unsigned int i =
static_cast<unsigned int>(std::log(static_cast<double>(n)) /
std::log(static_cast<double>(2)));
double d =
std::log(static_cast<double>(n)) / std::log(static_cast<double>(2));
unsigned int j = static_cast<unsigned int> (d);
assert (i == j);
}
I also know I can use bit shifting to come up with my result in a more predictable way. I am mostly curious why casting the double that results int he operation is any different than sticking that value into a double on the stack and casting the double on the stack.
In C++, floating point is allowed to do this sort of thing.
One possible explanation would be that the result of the division is calculated internally in a higher precision than double, and stored in a register with higher precision than double.
Converting this directly to unsigned int gives a different result to first converting this to double and then to unsigned int.
To see exactly what is going on , it might be helpful to look at the assembly output generated by your compiler for the 32-bit case.
Needless to say, you shouldn't write code that relies on exactness of floating point operations.

Precision loss with GMP

I have a program that reads numbers from a string to an mpz_t and then converts it to an mpf_t. Despite of being read correctly from the file, there is a precision loss when I convert them to mpf_t. The code is the following:
#include <gmp.h>
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char **argv) {
char* str = "632512364206354367378453";
mpz_t x;
mpz_init_set_str(x, str, 10);
mpf_t a;
mpf_init(a);
mpf_set_z(a, x);
gmp_printf("mpz_t: %Zd\n", x);
gmp_printf("mpf_t: %Ff\n", a);
}
The output for this example is:
mpz_t: 632512364206354367378453
mpf_t: 632512364206354367378000.000000
As you can see the last 3 digits are not correct. How can I avoid this? Is there any other function to perform this conversion?
Thanks
From the manual page:
Function: void mpf_init (mpf_t x)
Initialize x to 0. Normally, a variable should be initialized once only or at least be cleared, using mpf_clear, between initializations.
The precision of x is undefined unless a default precision has already
been established by a call to mpf_set_default_prec.
There's your problem.
Solution:
Function: void mpf_init2 (mpf_t x, mp_bitcnt_t prec)
Initialize x to 0 and set its precision to be at least prec bits. Normally, a variable should be initialized once only or at least be
cleared, using mpf_clear, between initializations.
That way, you can use the prec precision count argument to specify how many bits of precision you want.

Division in C++ not working as expected

I was working on something else, but everything came out as zero, so I made this minimalistic example, and the output is still 0.
#include <iostream>
int main(int argc, char** argv)
{
double f=3/5;
std::cout << f;
return 0;
}
What am I missing?
You are missing the fact that 3 and 5 are integers, so you are getting integer division. To make the compiler perform floating point division, make one of them a real number:
double f = 3.0 / 5;
It doesn't need to be .0, you can also do 3./5 or 3/5. or 3e+0 / 5 or 3 / 5e-0 or 0xCp-2 / 5 or... There only needs to be an indicator involved so that the compiler knows it's supposed to perform the division as floating point.
Another possibility: double f=double(3)/5. That's much more typing, but it leaves no doubt to what you are doing.
Or simply use double f=.6, that also does the trick...
try this:
double f = 3.0/5.0;
this should fix your problem
Try putting a .0 after one of the divisors. This will convert them into floating point literals.
You are using integers. You can many things to make your constants double like leftaroundabout states, however that is not good clean good. It is hard to read and confusing. If you want 3 and 5 make them 3.0 and 5.0. Everyone will know what you mean if they are forced to read your code. Much of what he/she states really requires you to know C/C++ and how floats are storage to make heads or tails.
In case, you save your generic variables with int and would like to obtain the ratio as double:
using namespace std;
int main()
{
int x = 7;
int y = 4;
double ratio;
ratio = static_cast<double>(x)/static_cast<double>(y);
cout << "ratio =\t"<<ratio<< endl;
}