mpf_class setting precision, assigning, freeing and converting to string - c++

I'm having trouble following the documentation for GMP https://gmplib.org/manual/C_002b_002b-Interface-Floats there is no examples for what I want to do. It might be more than 1 question but I don't think that they are too long for having 4 individual questions asking for each answer.
How can I initialize a mpf_class with 20 decimal places of precision
How can I set a value to my mpf_class with any precision I want, eg: mpf_class myNum = 3.1415926535897932000000000000000000000000123456789
How can I make an std::string hold the value of my mpf_class with the precision (lets say my std::string holds exactly the number above (3.14...)
From my understanding with gmp (without the mpf_class) you need to manage the memory, ie, mpf_clear() is there any memory managment that I need to do with mpf_class? If so what are they?

There are plenty of pretty nice examples in the GMP distribution itself, just look at the tests/ directory. Or in here, just search for the tag gmp and refine.
Note that to represent a decimal number in binary you need roughly speaking about log(10)/log(2) = 3.322... times binary digits than that of decimal digits. So, you use
Function: void mpf_class::set_prec (mp_bitcnt_t prec)
after delcaring the class instance, with precision set to 20 * 3.322, and GMP will alloc enough space for that to fit, and a little bit more, to fill in the integer number of limbs.
To initialize a mpf_t variable to arbitrary precision you can't use numeric constants in C/C++, like your example, because those numeric literals are interpreted as float or double according to your platform, and might not have the desired precision. In C++, use instead the string overload assignment, like so: mpf_class myNum; myNum = "3.1415926535897932000000000000000000000000123456789". C++ overload will call the mpf_init_set_str behind the scenes for you.
As above, but note that conversion from decimal to binary float has subtleties, see for example here and here. So, you have to understand what accuracy your decimal numbers have, and perhaps have a tolerance compare if required to do so (see my answer here).
With mpf_class you need to just declare the object instance and then delete it if you need to clear memory. With mpf_t you need to call mpf_init(), for example, and after using it, call mpf_clear() if needed. Note that all of those will be cleared from memory at program exit, as per operating system standards. You only need to worry about memory allocation, with malloc and free, and the alike, if you use the mpn_ raw "difficult to use" functions.

Related

Why is there a loss in precision when converting char * to float using sscanf_s or atof?

I am trying to convert a char * containing just a floating point value to a type float, but both sscanf_s and atof both produce the same invalid result.
char t[] = "2.10";
float aFloat( 0.0f ), bFloat( 0.0f );
sscanf_s( t, "%f", &aFloat );
bFloat = atof( t );
Output:
aFloat: 2.09999990
bFloat: 2.09999990
When I looked at similar questions in an attempt to ascertain the answer I attempted their solutions to no avail.
Converting char* to float or double
The solution given here was to include 'stdlib.h', and after doing so I changed the call to atof to an explicit call 'std::atof', but still no luck.
Unfortunately, not all floating point values can be explicitly represented in binary form. You will get the same result if you say
float myValue = 2.10;
I see the excellent answer in comments is missing (or I didn't find it there easily) one other option how to deal with it.
You should have wrote, why you need floating point number. If you by accident happen to work with monetary amounts (and not too huge ones), you can create custom parser of input values, and custom formatter for value output, to read it as 64b integer (*100), and work in your whole application with 100*amount values. If you are working with really huge amounts, use some library for big numbers, or you may create your own, working with char* numbers.
It's a special case of Fixed-point arithmetic.
If you are interested into "just to solve this", without coding too much, head for big numbers library anyway, even the *100 fixed-point variant is easy to write with bugs - if it's your first time and you don't have enough resources to do it correctly (TDD advised).
But definitely learn how the numbers are stored in computer, and why float/double can't represent all numbers. Float 2.1 for computer (base 2 used internally) is similar case to human's 1/3, which can't be represented in base 10 without infinite number of decimal places (and how 1.0 == 0.99999... in base 10). (thanks #tobi303)
After reading your new comment, if "Does this not have a big impact on financial applications?"
Answer: nope, zero impact, nobody sane (and professional) would create financial application with floats or doubles.

The use and the idea of integer to string conversion

I try to handle with big numbers in C++. One thing that I tried is installing the gmp library but this is not working properly on my computer (see this post). So I want to try another method and that is integer to string conversion.
But I dont get the idea of that. Let me make myself clear. For example we handle with a big integer. Lets say 2^1000. When, for example, I want to calculate 2^1000 mod 10 this is not possible (so far I know) with the normal libraries of c++. So my question is: Is it possible when converting my integer to a string and if the answer is yes:
How can I do arithmetic operations when I convert my integer to a string.
If you are using c++ predefined integer type, then 2^1000 is simply impossible. On your system maximum should be 2^16 or 2^32, max 2^64 (for long long). If you wanted to do that, you need to use (or implement yourself - what I don't recommend) infinite-precision integers.
You can convert normal int to string very easily with
... = std::to_string(/*Your int*/);
If you meant you want to do something like this:
amazing_to_string_conversion(1000000000000000000000000000000000000000000000)
It's not possible in any C++ implementation. The very number constant can't exist in code, it will many, many times overflow.
And if you consider implementing it yourself, it will probably K.O. you, because of very complicated calculations during division and non-trivial calculations like sqrt().

C++: Store large numbers in a float like PHP?

In PHP if you go above INT_MAX it will cast it as a float, allowing very high numbers to be formed (that are non-decimal as well), is this possible to do in C++ or are the way they store floating point/double precision numbers different?
The reason why is I am wishing to benchmark large factorials, but something such as 80! is way too large for an unsigned integer..
The language will not make the switch for you, but has the datatypes float and double, which are usually 32 bit and 64 bit IEEE floats, respectively.
A 64 bit double has enough range for 80!, but doesn't have enough precision to represent it exactly. The language doesn't have anything built in that can do that: you would need to use a big integer library, for example GMP.
try using the GMP library or there are several other Big Integer libraries provided for C++. You may also use string manipulation to calculate large factorials. Click here for the algorithm and its explanation.
C++ doesn't have such kind of "automatic casting" facilities, even if you could build a class that mimics such behavior by having an int and a float (a double would be even better, IIRC it lets you get up to 170!) private fields and some operator overloading black magic.
Anyhow, going from integers to fp you're going to lose precision, so, even if you can reach higher numbers, you aren't going to represent them exactly. Actually, if you're going in fp fields with factorials usually you could just use the Stirling's approximation (but I understand that in this case it do not apply, since it's a benchmark).
If you want to get to arbitrarily big factorials without losing precision, the usual solution is to use some bigint library; you can find several of them easily with Google.
Use one of bigint libraries, which allow you to create arbitrary precission ints in cost of performance. Or you have to write your own class to emulate PHPs hybrid float-int functionality
Something like this
class IntFloat {
union {
float fval;
int ival;
} val;
bool foatUsed;
public:
setVal(float val)
{
this->val.fval = val;
floatUsed = true;
}
setVal(int val)
{
this->val.ival = val;
floatUsed = false;
}
//additional code for getters, setters, operators etc
}
However what PHP does isn't worthy of imitation.
You can find list of big int libraries on wikipedia
PS:
"or are the way they store floating point/double precision numbers different?"
Yes it is different. C++ stores them straightly in target machine format, whle PHP uses intermediate representation (or bytecode, or in case of PHP opcode). Thus PHP converts number to machine format under the hood.
You can use __float128 (long double) if precision is enough and you compiler supports it.

changing float type to short but with same behaviour as float type variable

Is it possible to change the
float *pointer
type that is used in the VS c++ project
to some other type, so that it will still behave as a floating type but with less range?
I know that the floating point values never exceed some fixed value in that project, so I want to optimize the program by memory it uses. It doesn't need 4 bytes for each element of the 'float *pointer', 2 bytes will be enough I think. If I change a float to short and imitate the floating point behaviour, then it will use twice shorter memory. How to do it?
EDIT:
It calculates the probabilities. So there are divisions like
A / B
Where A < B,
And also B (and A) can be from 1 to 10 000.
There is a standard 16-bit floating point format described in IEEE 754-2008 called "binary16". It is specified as a format to store floating point values with reduced precisions. There is almost no compiler support for that yet (I think GCC supports it for certain ARM platforms), but it is quite easy to roll your own routines. This fellow:
http://blog.fpmurphy.com/2008/12/half-precision-floating-point-format_14.html
wrote a bit about it and also presents a routine to convert half-float <-> float.
Also, here seems to be a half-float C++ wrapper class:
half.h:
http://www.koders.com/cpp/fidABD00D95DE84C73BF0218AC621E400E07AA77B53.aspx
half.cpp
http://www.koders.com/cpp/fidF0DD0510FAAED03817A956D251787609BEB5989E.aspx
which supplies "HalfFloat" as a possible drop-in replacement type.
Maybe use fixed-point math? It all depends on value and precision you want to achieve.
http://www.eetimes.com/discussion/other/4024639/Fixed-point-math-in-C
For C there is a lot of code that makes fixed-point easy and I'm pretty sure there are also many C++ classes that make it even easier, but I don't know of any, I'm more into C.
The first, obvious, memory optimization would be to try and get rid of the pointer. If you can store just the float, that may, depending on the larger context, reduce your memory consumption from eight to four bytes already. (On a 64-Bit system, from twelve to four.)
Whether you can get by with a short depends on what your program does with the values. You may be able to use fix point arithmetic using an integral type such as a short, yes but your questions shows way too little context to judge that.
The code you posted and the text in the question do not deal with actual float, but with pointers to float. In all architectures I know of, the size of a pointer is the same regardless of the pointed type, so there would be no improvement in changing that to a short or char pointer.
Now, about the actual pointed elements, what is the range that you expect in your application? What is the precision you need? How many of those elements do you have? What are the memory constraints of your target platform? Unless the range and precision are small and the number of elements huge, just use floats. Also note that if you need floating point operations, storing any other type will require conversions before and after each operation, and you might be impacting performance.
Without greater knowledge of what you are doing, the ranges for short in many architectures are [-32k, 32k), where k stands for 1024. If your data ranges is [-32,32) and you can do with roughly 3 decimal digits you could use fixed point arithmetic with shorts, but there are few such situation.

C++: How to Convert From Float to String Without Rounding, Truncation or Padding? [duplicate]

This question already has answers here:
Why do I see a double variable initialized to some value like 21.4 as 21.399999618530273?
(14 answers)
Closed 6 years ago.
I am facing a problem and unable to resolve it. Need help from gurus. Here is sample code:-
float f=0.01f;
printf("%f",f);
if we check value in variable during debugging f contains '0.0099999998' value and output of printf is 0.010000.
a. Is there any way that we may force the compiler to assign same values to variable of float type?
b. I want to convert float to string/character array. How is it possible that only and only exactly same value be converted to string/character array. I want to make sure that no zeros are padded, no unwanted values are padded, no changes in digits as in above example.
It is impossible to accurately represent a base 10 decimal number using base 2 values, except for a very small number of values (such as 0.25). To get what you need, you have to switch from the float/double built-in types to some kind of decimal number package.
You could use boost::lexical_cast in this way:
float blah = 0.01;
string w = boost::lexical_cast<string>( blah );
The variable w will contain the text value 0.00999999978. But I can't see when you really need it.
It is preferred to use boost::format to accurately format a float as an string. The following code shows how to do it:
float blah = 0.01;
string w = str( boost::format("%d") % blah ); // w contains exactly "0.01" now
Have a look at this C++ reference. Specifically the section on precision:
float blah = 0.01;
printf ("%.2f\n", blah);
There are uncountably many real numbers.
There are only a finite number of values which the data types float, double, and long double can take.
That is, there will be uncountably many real numbers that cannot be represented exactly using those data types.
The reason that your debugger is giving you a different value is well explained in Mark Ransom's post.
Regarding printing a float without roundup, truncation and with fuller precision, you are missing the precision specifier - default precision for printf is typically 6 fractional digits.
try the following to get a precision of 10 digits:
float amount = 0.0099999998;
printf("%.10f", amount);
As a side note, a more C++ way (vs. C-style) to do things is with cout:
float amount = 0.0099999998;
cout.precision(10);
cout << amount << endl;
For (b), you could do
std::ostringstream os;
os << f;
std::string s = os.str();
In truth using the floating point processor or co-processor or section of the chip itself (most are now intergrated into the CPU), will never result in accurate mathematical results, but they do give a fairly rough accuracy, for more accurate results, you could consider defining a class "DecimalString", which uses nybbles as decimal characters and symbols... and attempt to mimic base 10 mathematics using strings... in that case, depending on how long you want to make the strings, you could even do away with the exponent part altogether a string 256 can represent 1x10^-254 upto 1^+255 in straight decimal using actual ASCII, shorter if you want a sign, but this may prove significantly slower. You could speed this by reversing the digit order, so from left to right they read
units,tens,hundreds,thousands....
Simple example
eg. "0021" becomes 1200
This would need "shifting" left and right to make the decimal points line up before routines as well, the best bet is to start with the ADD and SUB functions, as you will then build on them in the MUL and DIV functions. If you are on a large machine, you could make them theoretically as long as your heart desired!
Equally, you could use the stdlib.h, in there are the sprintf, ecvt and fcvt functions (or at least, there should be!).
int sprintf(char* dst,const char* fmt,...);
char *ecvt(double value, int ndig, int *dec, int *sign);
char *fcvt(double value, int ndig, int *dec, int *sign);
sprintf returns the number of characters it wrote to the string, for example
float f=12.00;
char buffer[32];
sprintf(buffer,"%4.2f",f) // will return 5, if it is an error it will return -1
ecvt and fcvt return characters to static char* locations containing the null terminated decimal representations of the numbers, with no decimal point, most significant number first, the offset of the decimal point is stored in dec, the sign in "sign" (1=-,0=+) ndig is the number of significant digits to store. If dec<0 then you have to pad with -dec zeros pror to the decimal point. I fyou are unsure, and you are not working on a Windows7 system (which will not run old DOS3 programs sometimes) look for TurboC version 2 for Dos 3, there are still one or two downloads available, it's a relatively small program from Borland which is a small Dos C/C++ edito/compiler and even comes with TASM, the 16 bit machine code 386/486 compile, it is covered in the help files as are many other useful nuggets of information.
All three routines are in "stdlib.h", or should be, though I have found that on VisualStudio2010 they are anything but standard, often overloaded with function dealing with WORD sized characters and asking you to use its own specific functions instead... "so much for standard library," I mutter to myself almost each and every time, "Maybe they out to get a better dictionary!"
You would need to consult your platform standards to determine how to best determine the correct format, you would need to display it as a*b^C, where 'a' is the integral component that holds the sign, 'b' is implementation defined (Likely fixed by a standard), and 'C' is the exponent used for that number.
Alternatively, you could just display it in hex, it'd mean nothing to a human, though, and it would still be binary for all practical purposes. (And just as portable!)
To answer your second question:
it IS possible to exactly and unambiguously represent floats as strings. However, this requires a hexadecimal representation. For instance, 1/16 = 0.1 and 10/16 is 0.A.
With hex floats, you can define a canonical representation. I'd personally use a fixed number of digits representing the underlying number of bits, but you could also decide to strip trailing zeroes. There's no confusion possible on which trailing digits are zero.
Since the representation is exact, the conversions are reversible: f==hexstring2float(float2hexstring(f))