I want to write doubles to a file but the string cast reduces the precision. Edit : I don't really cast but put the doubles in an ostringstream.
Is there another way than parsing each digit using modulo and division to write the doubles with more precision ?
Edit : My application needs to be portable
Here is my current code :
std::string arraytocsv(double v[], int size) {
std::ostringstream oss;
for (int i = 0; i < size; i++) {
oss << v[i] << ";";
}
oss << std::endl;
return os开发者_高级运维s.str();
}
I've had the precision() function, it works. Thanks
You can use precision function.
After declaring the string stream alter its behavior:
std::ostringstream oss;
oss.flags (std::ios::scientific);
oss.precision (std::numeric_limits<double>::digits10 + 1);
The first call, oss.flags()
, forces C++ I/O to use scientific notation on this string stream, even on something like pi. Printing numbers smaller in magnitude than 1.0 in fixed notation will lose precision while printing big numbers in fixed notation is extreme overkill.
The second call, oss.precision()
tells C++ I/O how many digits to print after the decimal point. Using digits10+1 tells it to print one superfluous digit; digits10
tells how many digits the system is capable of representing without loss of precision.
You will need to #include because of that std::numeric_limits<double>::digits10
.
Write it in binary. This is, by default, not portable (in that the serialized format is architecture dependent)
instead of
double myvalue = 123.4;
file << myvalue;
do
double myvalue = 123.4;
file.write((const char*) &myvalue, sizeof(myvalue));
Of course, this assumes that you don't require humans to read this (allthough, using UNIX tool like od
they might)
If you are just working on one single system, you could write the actual binary data out to the file, that'll give you an exact copy. If you want to write to a text file, convert the binary to Base64 or something like that.
std::ofstream myfile("file.bin");
double x;
myfile.write(reinterpret_cast<char*>(&x), sizeof(x));
// later
std::ifstream yourfile("file.bin");
double x;
myfile.read(reinterpret_cast<char*>(&x), sizeof(x));
Optionally, encode the bytestream as base64. If you want to store long doubles and you are going for base64-encoding, note that the long double is usually only 10 bytes, so you can ignore the padding that it usually gets when you serialize.
If you plan to exchange data between different platforms, but all of which use IEEE floats, you should probably be more careful and document the endianness of the file format. In that case, writing an ASCII string with base64-encoding would be more portable. To exchange data between platforms that do not all use the same binary float representation, you'd have to work even harder...
精彩评论