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.
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.
This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 5 years ago.
I am working with a MATLAB optimization platform for black-box cost functions (BBCF).
To make the user free-handed, the utilized BBCF can be any executable file which inputs the input parameters of BBF and must output (return) the cost value of BBCF, so that the MATLAB BBCF optimizer finds the best (least cost) input parameter.
Considering that, from the one hand, my BBCF is implemented in C++, and from the other hand the cost value is a double (real number), I need to compile my code to an EXE file that outputs (returns) double.
But, to the best of my knowledge, when I compile a C++ code to EXE, it "mainly" compiles the main() function and its output is the output of main() function (i.e. 0 if running successful!).
An idea could be using a main function that returns double, and then, compiling such main() to EXE but, unfortunately, it is not possible in C++ (as explained in this link or as claimed in the 3rd answer of this question to be a bug of C++ neither of which are business of this question).
Can anyone provide an idea by which the EXE compiled form of a C++ code, outputs (returns) a double value?
This is not 'a bug in C++' (by the way, the bug might be in some C++ compiler, not in the language itself) - it's described in the standard that main() should return an integer:
http://en.cppreference.com/w/cpp/language/main_function
Regarding how to return a non-int from an executable, there are a couple of ways to do that. Two simplest (in terms of how to implement them) solutions come to my mind:
Save it to a file. Then either monitor that file in Matlab for changes (e.g. compare timestamps) or read after each execution of your EXE file depending on how you're going to use it. Not very efficient solution, but does the job and probably the performance penalty is negligible to that of your other calculations.
If you are fine with your cost value losing some numerical accuracy, you can just multiply the double value by some number (the larger this number, the more decimal places you will retain). Then round it, cast it to an int, have it returned from main(), cast it back to double in matlab and divide by the same number. The number used as the multiplier should be a power of 2 so that it doesn't introduce additional rounding errors. This method might be particularly useful if your cost value takes the values limited to the range [0, 1] or if you can normalize it to these values and you know that variations less than some threshold are not important.
In English, 'shall' is an even stronger imperative than 'must'.
Making a change like this would require changes to the operating system and shell. Such changes are unlikely to happen.
The easiest way to pass a double return would to to write it to standard output. Alternatively there are several methods available for interprocess communication.
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.
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.
I have a problem with casting from float to double when fread;
fread(doublePointer,sizeofFloat,500,f);
if i change double pointer to float pointer, it works just fine.
However,i need it to be double pointer for laster on, and i thought when i write from small data type (float)to bigger data type(double)'s memory, it should be fine. but it turns out it doesnt work as i expected.
what is wrong with it, and how do i solve this problem.
i know i can solve it by converting it one by one. but i have a huge amount of data. and i dont wanna extra 9000000+ round of converting.. that would be very expensive. and is there any trick i can solve it?
is there any c++/c tricks
thanks
If you write float-formatted data into a double, you're only going to get garbage as a result. Sure, you won't overflow your buffer, but that's not the only problem - it's still going to be finding two floats where it expects a double. You need to read it as a float, then convert - casting (even implicitly) in this manner lets the compiler know that the data was originally a float and needs to be converted:
float temp[500];
int i;
fread(temp, sizeof(temp[0]), 500, f);
for (i = 0; i < 500; i++)
doublePointer[i] = temp[i];
Suppose for example a float is 4 bytes on your computer. If you read 500 floats then you read 2000 bytes, one float per float and the result is correct.
Suppose for example a double is 8 bytes on your computer. If you read 500 floats then you read 2000 bytes, but you're reading them into 250 doubles, 2 floats per double, and the result is nonsense.
If your file has 500 floats you have to read 500 floats. Cast each float value to a double value. You can convert each numeric value that way.
When you abuse a pointer, pretending that the pointer points to a type of data that it doesn't really point to, then you're not converting each numeric value, you're preserving nonsense as nonsense.
Edit: You added to your question "and i dont wanna extra 9000000+ round of converting.. that would be very expensive. and is there any trick i can solve it?" The answer is yes, you can use a trick of keeping your floats as floats. If you don't want to convert to doubles then don't convert to doubles, just keep your floats as floats.
9000000 conversions from float to double is nothing. fread into a float array, then convert that into a double array.
Benchmark this code scientifically, don't guess about where the slowdowns might be.
If you're bottlenecked on the conversion, write a unrolled, vectorized conversion loop, or use one from a commercial vector library.
If it's still too slow, tile your reads so you read in your float data in batches of a few pages that fit in L1 cache, then convert those to double, then read the next few pages and convert those to double, etc.
If it's still too slow, investigate loading your data lazily so only the parts that are needed get loaded, and only when they are used.
A modern x86 core is capable of doing two float->double conversions per cycle in a hand-tuned vectorized loop; at 2GHz, that's 4 billion conversions per second per core. 9 million conversions is small change -- my laptop does it in less than 1 millisecond.
Alternatively, just convert the whole dataset to double once, and read it in that way from now on. Problem solved.
I would look at this from a different perspective. If the data is stored as float, then that is all the precision it will ever have. There is no point in converting to double until the rules of floating point arithmetic require it.
So I would allocate a buffer for the 500 (or whatever) floats, and read them from the data file with one suitable call to fread():
float *databuffer;
//...
databuffer = malloc(500 * sizeof(float));
fread(databuffer, sizeof(Float), 500, f);
Later, use the data in whatever math it needs to participate in. It will be promoted to double if required. Don't forget to eventually free the buffer after it is no longer needed.
If your results really do have all the precision of a double, then use a fresh buffer of doubles to hold them. However, if they are to be written back to file as float, then you will eventually need to put them into a buffer of floats.
Note that reading and writing files for interchange often needs to be considered a separate problem from efficient storage and usage of data in memory. It is often necessary to read a file and process each individual value in some way. For example, a portable program might be required to handle data written by a system using a different byte order. Less frequently today, you might find that even the layout of the bits in a float differs between systems. In general, this problem is often best solved by deferring to a library implementing a standard such as XDR (defined by RFC 4506) that was designed to deal with binary portability.