Is there a library class to represent floating point numbers? - c++

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.

Related

Double to string conversions for calculator

I am currently developing a cCalc, which is a graphical user interface calculator that looks like the built-in calculator in Windows 10 in engineering mode. My project is based on C++17, using FLTK as a GUI wrapper, and long double as the main type for working with numbers. I am using MinGW 10.2.
Today, I discovered a problem with converting from long double type to std::string, since I don't know how to choose the number of decimal places. The C++ language has built-in capabilities for converting from long double to std::string, but they are not suitable because:
std::to_string(long double) always uses six digits of decimal places. If the user wants to count 40 + 1, he expects 41 but 41.000000 will not be quite expected.
std::ostringstream s with s.precision(n) is also a bad idea. Any option with a fixed precision will not work, as the real part with important digits may be discarded.
std::ostringstream s without s.precision(n) is not suitable, since the automatic selection of the number of decimal places is not always correct. For example:
std::ostringstream s;
s << 3.14159265L;
std::cout << s.str();
This will give 3.14159, 3 digits with valuable information have been lost.
I was programming in C# a few years ago, and as far as I remember, the easy way of System.Convert.ToString(double d) worked very well.
Question:
What is a good and free-licensed implementation that solves the described problem? I am expecting an implementation that for large (or small) numbers uses scientific notation.
Also, I do not want to add huge libraries, like Boost, to my project.

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.

C++ convert floating point number to string

I am trying to convert a floating point number to string. I know you can do it using ostringstream & sprintf etc. but in the project I am working I am trying to do it using my own functions only (I am creating my own string class without using any outside functions). I don't want a perfect representation e.g. I don't mind it if this happens with large or small number: 1.0420753e+4 like it does with the standard stringstream.
I know how floating point numbers work (e.g. sign, exponent, mantissa) and how they are represented in a different way from what they are displayed as (that is why its difficult). I know this is possible because the std c++ library can do it - I just don't know how to do it myself.
EDIT: I have created my own integer version of this (converts int to my own CString class).
First, do not do this yourself. iOS has standard C++ features for formatting floating-point objects, and I expect Android does too.
Second, do not do this yourself. It is hard to do without rounding errors. The techniques for doing it are already known and published, and you should use good references rather than the algorithms you will generally find on Stack Overflow. The classic paper for this is Correctly Rounded Binary-Decimal and Decimal-Binary Conversions by David M. Gay, and here is code from David Gay.
Simple method: Divide by 10 until the value is ≤ 1. This gives you the number of decimals after which you should print the .. Multiply the original number by 10 for each digit you want after the ., and round. Stringify the resulting integer, and insert the ..
Uhm, if you really want to reinvent your own square wheel, then probably the easiest way is to write converter from float to int(you said you know how bit pattern works), or maybe even 2 ints - one for fractional part, other for the rest, then print them REUSING code that already exists
Use ostringstream -:
double d = 2.7818;
std::ostringstream ss;
ss << d;
std::cout << ss.str() << std::endl;

Comparisons of arbitrary arithmetic types: does anyone know an implementation?

While writing several math utilities I bumped into need to implement generic utility that can perform comparisons between any two fundamental arithmetic types. As I began coding, it became clear that this operation is not as straightforward as it seems, since I need correct handling of corner cases, especially when the types have different precision, i.e. rounding strategy during conversion between types becomes important. Consider:
float a1 = 4.8f;
int a2 = 4;
assert(a2 != (int) a1); //fails erroneously since we truncated a1
float b1 = 40000000.0f; //can represent only 40000000 and 40000004 accurately
long b2 = 40000002;
assert(b1 != (float) b2); //fails erroneously since we now truncated b2
The above can be implemented using c++0x type traits to automatically select the appropriate algorithm according to the template arguments supplied to the comparison function. However, this is quite complex and there's quite a lot of places where bugs can creep, so I don't think inventing everything myself is worthwhile. Does anyone know a library that implements the above correctly?
You may want to look into GNU's MP Bignum library at http://gmplib.org/. From their page:
GMP is a free library for arbitrary precision arithmetic, operating on
signed integers, rational numbers, and floating point numbers. There
is no practical limit to the precision except the ones implied by the
available memory in the machine GMP runs on. GMP has a rich set of
functions, and the functions have a regular interface.
GMP is carefully designed to be as fast as possible, both for small
operands and for huge operands. The speed is achieved by using
fullwords as the basic arithmetic type, by using fast algorithms, with
highly optimised assembly code for the most common inner loops for a
lot of CPUs, and by a general emphasis on speed.

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.