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.
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().
When representing double number its precision corrupts in some degree. For example number 37.3 can be represented as 37.29999999999991.
I need reestablishing of corrupted double number (My project requires that). One approach is converting double into CString.
double d = 37.3;
CString str;
str.Format("%.10f", d);
Output: str = 37.3;
By this way I could reestablish corrupted d. However, I found a counterexample. If I set
d = 37.3500;
then its double representation sometimes be equal to 37.349998474121094. When converting d to CString output is still 37.3499984741, which is not equal to 37.3500 actually.
Why converting 37.3500 didn't give desired answer, while 37.3 gave? Is there any ways to reestablish double?
Thanks.
Why converting 37.3500 didn't give desired answer, while 37.3 gave?
By accident. The representation of 37.3 happened to be close enough that rounding to 10 decimal places gave the expected result, while 37.3499984741 didn't.
Is there any ways to reestablish double?
No, once information has been lost, you can't recover it. If you need an exact representation of decimal numbers, then you'll need a different format than binary floating point. There's no suitable decimal type in the C++ language or standard library; depending on your needs, you might consider libraries such as Boost.Multiprecision or GMP. Alternatively, if you can limit the number of decimal places you need, you might be able to multiply all your numbers by that scale and work with exact integers.
It can be done to some extend, but not easily. Since the string representation is base 10, but the internal representation in base 2, there is rounding involved when converting one into the other. So when you convert the decimal "37.35" to double, the result is not identical to the original number. When converting that number back to a string, the computer cannot know for sure what number was there in the first place, because there are several decimal numbers that result in the same double. However, you can add the constraint that you want the shortest possible decimal string that results in the given double, then there is a very good chance that it recovers your original string precisely. An algorithm using that constraint has been developed by David Gay. Here's the source code, you need both g_fmt.c and dtoa.c, and here is a paper about it. This is the default algorithm used in Python since Version 3.1.
My question has no practical application. I'm just interested. Suppose, I have a double value and I want to obtain its string representation similarly to the printf function. How would I do that without the C runtime library? Let's suppose I'm on the x86 architecture.
Given that you state your question has no practical application, I figure you're trying to learn about floating point number representations.
Thus, if you're looking for a solution without using any library support, start with the format specification. From that you can discern the various "special" values (Infinity, NAN, etc) as well as decoding/calculating the actual numeric value. Once you have the significand and exponent, you know where to put the decimal point. You'll have to write your own itoa type routine. For radices which are a power of two, this can be as simple as a lookup table. For decimal, you'll have to do a little extra math.
you can get all values on left side by (double % 10) and then divide by 10 every time.
they will be in right to left.
to get values on right of dot you have to multiply by 10 and then (double % 10). they will be in left-to-right.
If you want to do it simply with a "close enough" result, see my article http://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/ . It describes a simple program that uses floating-point to convert from floating-point to decimal, and explains why that approach can never be accurate for all conversions. (The program doesn't do decimal rounding like printf, but that should be easy enough to add.)
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))