One common question ,may be I am wrong at this point but last two hours on google not give me any answer,
Question is how to convert CString to float without using std: library in c++.
I tried with wcstod() function but, This function has very different behaviour.
Please find following code,
CString Tempconvert = "32.001";
double TempConvertedValue = wcstod(Tempconvert,NULL);
So, Finally TempConvertedValue should have value 32.001. But i am getting TempConvertedValue = 32.000999999999998
Please provide me any help which convert
String "32.001" to float 32.001 only. Without using std: library.
What you see is an example of floating point internal representation. You can have a look here to see how double are stored in memory. See also this question to know why debugger shows you this value.
With this storing format, it is not possible to represent a decimal number exactly. That is why money calculations usually use special decimal types that are either custom or part of the programming language.
Related
I receive a JSON Array from a server which looks like: [0.00015099, 1, -672.41163]
These values are orderbook entries. If I try to parse all values as double, my price differs slightly from the price in the JSON array. It is clear for me, that this happens because of the double conversion, but how to program around some crazy stuff like this?
Need these values also for calculation, compares etc.
I am using Qt5 and C++.
Any hint?
Well, you should use some Decimal type if you want to deal with money to be on a safe side. Unfortunately, Qt does not have decimal type for some reason. So, you may end up with some rounding rules/conventions if you have no other choice. Otherwise you'd better to implement your own implementation or use some existing solution like qdecimal.
I'm working in a XE6 project, but this may apply to other version of builder as well.
I'm looking at a function name, which I think may be misleading. I'm curious if StrToFloat() returns a float or if it returns a double. I found an alternative, which is .ToDouble() but we have a bunch of references in our code already that uses StrToFloat(). I wish to verify that I'm getting the proper precision that doubles offer.
I've done a couple tests like:
UnicodeString temp = "1234567890.12345678901234567890";
double a = StrToFloat(temp);
double b = temp.ToDouble();
These seem to give the same values from the tests I've done, but I wish to verify the StrToFloat() is the same as .ToDouble()
I found enough references to answer my own question...
StrToFloat() returns an extended and an extended is a long double.
.ToDouble() returns a double.
So short answer is they are not the same, and vary as shown above.
References:
StrToFloat():
http://docwiki.embarcadero.com/Libraries/XE6/en/System.SysUtils.StrToFloat
Extended:
http://docwiki.embarcadero.com/Libraries/XE6/en/System.Extended
.ToDouble():
http://docwiki.embarcadero.com/Libraries/XE2/en/System.UnicodeString.ToDouble
long double are more precise then double precision. http://en.wikipedia.org/wiki/Long_double
What is the best way to render double precision numbers as strings in C++?
I ran across the article Here be dragons: advances in problems you didn’t even know you had which discusses printing floating point numbers.
I have been using sprintf. I don't understand why I would need to modify the code?
If you are happy with sprintf_s you shouldn't change. However if you need to format your output in a way that is not supported by your library, you might need to reimplement a specialized version of sprintf (with any of the known algorithms).
For example JavaScript has very precise requirements on how its numbers must be printed (see section 9.8.1 of the specification). The correct output can't be accomplished by simply calling sprintf. Indeed, Grisu has been developed to implement correct number-printing for a JavaScript compiler.
Grisu is also faster than sprintf, but unless floating-point printing is a bottleneck in your application this should not be a reason to switch to a different library.
Ahah !
The problem outlined in the article you give is that for some numbers, the computer displays something that is theoritically correct but not what we, humans, would have used.
For example, like the article says, 1.2999999... = 1.3, so if your result is 1.3, it's (quite) correct for the computer to display it as 1.299999999... But that's not what you would have seen...
Now the question is why does the computer do that ? The reason is the computer compute in base 2 (binary) and that we usually compute in base 10 (decimal). The results are the same (thanks god !) but the internal storage and the representation are not.
Some numbers looks nice when displayed in base 10, like 1.3 for example, but others don't, for example 1/3 = 0.333333333.... It's the same in base 2, some numbers "looks" nice in base 2 (usually when composed of fractions of 2) and other not. When the computer stores number internally, it may not be able to store it "exactly" and store the closest possible representation, even if the number looked "finite" in decimal. So yes, in this case, it "drifts" a little bit. If you do that again and again, you may lose precision. But there is no other way (unless using special math libs able to store fractions)
The problem arise when the computer tries to give you back in base 10 the number you gave it. Then the computer may gives you 1.299999 instead of the 1.3 you were expected.
That's also the reason why you should never compare floats with ==, <, >, but instead use the special functions islessgreater(a, b) isgreater(a, b) etc.
So the actual function you use (sprintf) is fine and as exact as it can, it gives you correct values, you just have to know that when dealing with floats, 1.2999999 at maximum precision is OK if you were expecting 1.3
Now if you want to "pretty print" those numbers to have the best "human" representation (base 10), you may want to use a special library, like your grisu3 which will try to undo the drift that may have happen and align the number to the closest base 10 representation.
Now the library cannot use a crystal ball and find what numbers were drifted or not, so it may happen that you really meant 1.2999999 at maximum precision as stored in the computer and the lib will "convert" it to 1.3... But it's not worse nor less precise than displaying 1.29999 instead of 1.3.
If you need a good readability, such lib will be useful. If not, it's just a waste of time.
Hope this help !
The best way to do this in any reasonable language is:
Use your language's runtime library. Don't ever roll your own. Even if you have the knowledge and curiosity to write it, you don't want to test it and you don't want to maintain it.
If you notice any misbehavior from the runtime library conversion, file a bug.
If these conversions are a measurable bottleneck for your program, don't try to make them faster. Instead, find a way to avoid doing them at all. Instead of storing numbers as strings, just store the floating-point data (after possibly controlling for endianness). If you need a string representation, use a hexadecimal floating-point format instead.
I don't mean to discourage you, or anyone. These are actually fascinating functions to work on, but they are also shocking complex, and trying to design good test coverage for any non-naive implementation is even more involved. Don't get started unless you're prepared to spend months thinking about the problem.
You might want to use something like Grisu (or a faster method) because it gives you the shortest decimal representation with round trip guarantee unlike sprintf which only takes a fixed precision. The good news is that C++20 includes std::format that gives you this by default. For example:
printf("%.*g", std::numeric_limits<double>::max_digits10, 0.3);
prints 0.29999999999999999 while
puts(fmt::format("{}", 0.3).c_str());
prints 0.3 (godbolt).
In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):
fmt::print("{}", 0.3);
Disclaimer: I'm the author of {fmt} and C++20 std::format.
In C++ why aren't you using iostreams? You should probably be using cout for the console and ostringstream for string-oriented output (unless you have a very specific need to use a printf family method).
You shouldn't worry about formatting performance unless actual profiling shows that CPU is the bottleneck (compared to say I/O).
void outputdouble( ostringstream & oss, double d )
{
oss.precision( 5 );
oss << d;
}
http://www.cplusplus.com/reference/iostream/ostringstream/
I wrote some parameters (all of type double) to a file for use in performing some complex computations. I write the parameters to the files like so:
refStatsOut << "SomeParam:" << value_of_type_double << endl;
where refStatsOut is an ofstreamparameter. There are four such parameters, each of type double. What I see as written to the file is different from what its actual value is (in terms of loss of precision). As an example, if value_of_type_double had a value -28.07270379934792, then what I see as written in the file is -28.0727.
Also, once these stats have been computed and written I run different programs that use these statistics. The files are read and the values are initially stored as std::strings and then converted to double via atof functions. This results in the values that I have shown above and ruins the computations further down.
My question is this:
1. Is there a way to increase the resolution with which one can write values (of type double and the like) to a file so as to NOT lose any precision?
2. Could this also be a problem of std::string to double conversion with atof? If so, what other function could I use to solve this?
P.S: Please let me know in case some of the details in this question are not clear. I will try to update them and provide more details.
You can use the setprecision function.
ofstream your_file;
you can use your_file.precision(X);
The main difference between precision() and setPrecision() is that precision returns the current precision and setPrecision doesn't. Therefore, you can use precision like this.
streamsize old_precision = your_file.precision(X);
// do what ever you want
//restore precision
your_file.precision(old_precision);
a double is basically a 64-bit integer, if you want a cheap way of writing it out, you can do something like this (note I'm assuming that your compiler uses long for 64-bit ints)
double value = 32985.932235;
long *saveme = (long*)&value;
Just beware of the caveat that the saved value may not remain the same if loaded back on a different architecture.
i have written a program and it works with 3D coordinates (i.e. x,y,z).
input data for my program was like
50903.85 21274.97 15.03
50903.57 21274.96 15.08
50903.33 21274.95 15.17
and i got the output with some more columns. So, i got the same x,y,z for my output file.
50903.85 21274.97 15.03
50903.57 21274.96 15.08
50903.33 21274.95 15.17
so, my program works properly, i guess.
then, i used another data set, having more digits than the previous data,
512330.98 5403752.71 330.39
512331.01 5403754.18 329.44
512331.06 5403755.59 329.56
and my output was like;
512331 5.40375e+006 330.39
512331 5.40375e+006 329.44
512331 5.40376e+006 329.56
here, i am not able to get real values. and x values are also rounded. i cant think what should be the reason?
in my program, i used "double" for assigning variables for x,y,z values. SO, i would like to know what is the maximum numerical value that can be refereed to double?
if someone need to work with very long values, what should be the relevant variable?
Numbers aren't changing, you are just seeing a different notation change there. Perhaps you are using something other than %f to format your doubles? See printf format parameters.
Better yet, check out this StackOverflow question: How to avoid scientific notation for large numbers?
Those numbers, such as 5.40375e+006, are another way of representing doubles. When they get sufficiently large, they are by default printed in scientific notation. 5.40375e+006 is 5.40375 * 10^6, or 5403750.
Have a look at this http://www.cplusplus.com/reference/clibrary/cfloat/
Doubles have about 16 decimals of accuracy (source), so you shouldn't have any problem here, unless you're printing floats.