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

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.

Related

mpf_class setting precision, assigning, freeing and converting to string

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.

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.

Type for large currency values in C++

What type should i use in C++ to store large currecy values like 5231451.3245114414? It should allow to store 10 or even more decimal digits.
It depends on how large your values are, and more importantly on the required precision.
If all numbers have the same precision and scale, say 10 places after the decimal point and no bigger than one million, then you could just use long integers (multiply everything by 1010, etc.).
If you truly need arbitrary scales and precision, you won't get around an arbitrary-precision library. A quick search turned up mpdecimal, but there may be others. Combining the fixed-point approach with arbitrary precision, you could also just use libgmp for arbitrary-precision integers but treat them all as units of 1010.
You probably need a custom type that mimics what Java's BigDecimal does.
A 64-bit double precision number is only accurate to 17 digits, so you'll have to do better than that.
You may try to check if GMP suits what you need. It got a C++ wrapper if I remember correctly.
If you have to work with monetary values you probably want a fixed-point decimal class, so something like this should do the trick.
Since you want all that precision (out of curiosity: why do you need that for monetary amounts?) you should probably use a 64 bit integer as its base type (it should be enough for up to ~18 total decimal digits). If that still isn't enough you'll have to use some biginteger library to have an arbitrarily-big integer as the base for the fixed point decimal class.
Have you looked at decNumber++? Link can be found at http://speleotrove.com/decimal/ ?
Thanks you all for your answers. I found the most appropriate solution myself. It's just one file that does everything i need - C++ wrapper class for the OLE Automation type DECIMAL. It's really light (no additional heavy libraries or files) and powerfull and can handle REALLY BIG numbers.

C++: how to truncate the double in efficient way?

I would like to truncate the float to 4 digits.
Are there some efficient way to do that?
My current solution is:
double roundDBL(double d,unsigned int p=4)
{
unsigned int fac=pow(10,p);
double facinv=1.0/static_cast<double>(fac);
double x=static_cast<unsigned int>(d*fac)*facinv;
return x;
}
but using pow and delete seems to me not so efficient.
kind regards
Arman.
round(d*10000.0)/10000.0;
or if p must be variable;
double f = pow(10,p);
round(d*f)/f;
round will usually be compiled as a single instruction that is faster than converting to an integer and back. Profile to verify.
Note that a double may not have an accurate representation to 4 decimal places. You will not truly be able to truncate an arbitrary double, just find the nearest approximation.
Efficiency depends on your platform.
Whatever methods you try, you should profile to make sure
the efficiency is required (and a straightforward implementation is not fast enough for you)
the method you're trying is faster than others for your application on real data
You could multiply by 10000, truncate as an integer, and divide again. Converting between double and int might be faster or slower for you.
You could truncate on output, e.g. a printf format string of "%.4f"
You could replace pow with a more efficient integer-based variant instead. There's one here on Stack Overflow: The most efficient way to implement an integer based power function pow(int, int)
Also, if you can accept some inaccuracy, replace the divide with a multiply. Divisions are one of the slowest common math operations.
Other than that, I'll echo what others have said and simply truncate on output, unless you actually need to use the truncated double in calculations.
If you need to perform exact calculations that involve decimal digits, then stop using double right now! It's not the right data type for your purpose. You will not get actually rounded decimal values. Almost all values will (after truncation, not matter what method you use) be in fact be something like 1,000999999999999841, not 1,0001.
That's because double is implemented using binary fractions, not decimal ones. There are decimal types you can use instead that will work correctly. They will be a lot slower, but then, if the result does not need to be correct, I know a method to make it infinitely fast...

Is there a library class to represent floating point numbers?

I am writing an application which does a lot of manipulation with decimal numbers (e.g. 57.65). As multiplications and divisions quickly erode their accuracy, I would like to store the numbers in a class which preserves their accuracy after manipulation, rather than rely on float and double.
I am talking about something like this:
class FloatingPointNumber {
private:
long m_mantissa;
int m_dps; // decimal points
// so for example 57.65 would be represented as m_mantissa=5765, m_dps=2
public:
// Overloaded function for addition
FloatingPointNumber operator+(FloatingPointNumber n);
// Other operator overloads follow
}
While it is possible for me to write such a class, it feels a bit like reinventing the wheel and I am sure that there must be some library class somewhere which does this (although this does not seem to exist in STL).
Does anybody know of such a library? Many thanks.
Do you mean something like this ?
#include "ttmath/ttmath.h"
#include <iostream>
int main()
{
// bigdouble consists of 1024*4 bytes for the mantissa
// and 256*4 bytes for the exponent.
// This is because my machine is 32-bit!
typedef ttmath::Big<1024, 256> bigdouble; // <Mantissa, Exponent>
bigdouble x = 5.05544;
bigdouble y = "54145454.15484854120248541841854158417";
bigdouble z = x * y * 0.01;
std::cout << z;
return 0;
}
You can specify the number of machine words in the mantissa and the exponent as you like.
I have used TTMath to solve Project Euler puzzles, and I am really pleased with it. I think it is relatively stable and the author is very kind if you have questions.
EDIT:: I have also used MAPM in the past. It represents big floats in base 100, so there would be no problem converting decimal numbers to base 100, unlike base 2. TTMAT uses base 2 to represents big floats. It is stable since 2000 as the library page claims. It has been used in many applications as you can see in the library page. It is a C library with a nice C++ wrapper.
MAPM nextPrime(){
static MAPM prime = 3;
MAPM retPrime = prime;
prime += 2;
while( isPrime( prime ) == false )
prime += 2;
return retPrime;
}
BTW, If you are interested in GMP and you are using VS, then you can check the MPIR which is GMP port for Windows ;) for me I find TTMath more than pleasing and easier/faster than all of what I tried because the library does stack allocations without touching the heap in anyway. Basically it is not an arbitrary precision library, you specify the precision at compile-time as shown above.
There is a list of libraries here.
I have never tried any of them so I can't recommend a single one, however this one is part of the GNU Project so it can't be half bad.
If you want to roll your own, Binary Coded Decimal is probably your best bet.
A list of decimal arithmetic packages, included Robert Klarer’s decNumber++, which implements the interfaces specified in the forthcoming ISO Technical Report on decimal arithmetic types in C++: ISO/IEC TR 24733: C++ Decimal Floating-Point Arithmetic Extensions
The Multiple Precision Floating point with correct Rounding library, but if I remember correctly, it is binary floating point
I have no experience with these libraries, but just as a matter of awareness, there have been 2 major developments that I think are relevant to this question in the last few years...
"posits" - a new floating-point format that is more efficient and less "messy" than IEEE754.
C# 11 has introduced "static abstract interface members" which enables (for our purposes) implementing new numeric types while getting all the same benefits of the built-in numeric types in terms of operator overloading, etc... i.e. truly generic numeric types in C#.
I know of no implementations of "posits" in C#, nor is C# 11 released yet. But again -- these are salient developments related to the question.