Is there a way to configure ostream using iomanip to output floating point numbers as follows:
0.00000000000000E+0000
3.99147034531211E-0003
...
I am translating code from pascal to C++ and I need to output numbers in exactly same format. It is preferable to use std::ofstream instead of fprintf or other C library functions.
One way to do this is with some string manipulation. Format to a stringstream using scientific notation, then split the string on the 'e'. Now you have the parts you can format yourself.
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
std::string format(double val)
{
std::ostringstream oss;
oss << std::scientific << std::setprecision(14) << val;
auto result = oss.str();
auto match = result.find('e');
if (match == std::string::npos)
{
// Should never get here -- maybe throw
}
oss.str("");
auto exp = std::stoi(result.substr(match+1));
oss << result.substr(0, match) << 'E'
<< std::setw(5) << std::setfill('0')
<< std::internal << std::showpos << exp;
result = oss.str();
return result;
}
int main()
{
std::cout << format(3.99147034531211e-3) << '\n';
std::cout << format(6.02214085774e23) << '\n';
}
Output:
3.99147034531211E-0003
6.02214085774000E+0023
You will need to use std::fixed
Sample program:
#include <iostream>
#include <fstream>
int main()
{
float f1 = -187.33667, f2 = 0.0;
std::ofstream out("test.bin",std::ios_base::binary);
if(out.good())
{
std::cout << "Writing floating point number: " << std::fixed << f1 << std::endl;
out.write((char *)&f1,sizeof(float));
out.close();
}
std::ifstream in("test.bin",std::ios_base::binary);
if(in.good())
{
in.read((char *)&f2,sizeof(float));
std::cout << "Reading floating point number: " << std::fixed << f2 << std::endl;
}
return 0;
}
OP by user Texan40. For more info: Here
Related
Im working on a college project and it requires big number like 43,000,000 but everytime i launch the program it gives me something like this 43000,000. I already used std::fixed and precision but it doesnt add the second comma.
this is the code:
double PreEnCol() {
if (marca == 1)
return (105.000*562);
else if (marca == 2)
return (65.000*562);
else if (marca == 3)
return (54.000*562);
else if (marca == 4)
return (125.000*562);
else if (marca == 5)
return (129.000*562);
else if (marca == 6)
return (85.900*562);
}
string toString(){
stringstream s;
s << endl;
s << std::fixed << std::setprecision(1) << "Precio en colones: "<<PreEnCol() << endl;
return s.str();
}
Please i need help with this i've been dealing with this problem for hours.
Mostly your output depend on your default locale. You need to override you whole locale OR part of locale of you interest.
Below code helps you to override part of locale which is responsible for printing commas in number.
#include <iostream>
#include <sstream>
#include <iomanip>
#include <locale>
struct Sep3Digit : std::numpunct<char> {
std::string do_grouping() const { return "\003"; }
};
std::string FormatWithCommas(double d)
{
std::stringstream ss;
ss.imbue(std::locale(std::cout.getloc(), new Sep3Digit));
ss << std::fixed << d;
return ss.str();
}
int main()
{
std::cout<<FormatWithCommas(std::numeric_limits<double>::max())<<std::endl;
return 0;
}
You can usually do that with default system locale:
#include <locale>
string toString(){
stringstream s;
s << endl;
s.imbue(std::locale("")); // <-- set locale. OR: std::locale("en_US")
s << std::fixed << std::setprecision(1) << "Precio en colones: "<<PreEnCol() << endl;
return s.str();
}
Note that this will print 43000000 as 43,000,000 in some parts of the world, or as 43.000.000 in others where '.' is used as grouping separator.
Here's full example:
#include <locale>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;
string toString(int n)
{
stringstream s;
s << endl;
s.imbue(std::locale("")); // <-- set locale
s << std::fixed << std::setprecision(1) << "Precio en colones: "<< n << endl;
return s.str();
}
int main()
{
int n = 43000000;
cout << "formatted " << n << ": " << toString(n) << endl;
}
It produces this output:
formatted 43000000:
Precio en colones: 43,000,000
From the console i am asking for a hexadecimal string to convert to a pointer to reference an item in memory.
#include <iostream>
#include <sstream>
#include <Windows.h>
int char_to_pointer(std::string input);
int main() {
int sample = 100; // lets say this address is 0xc1f1
std::string input_;
std::cout << "addr:" << &sample << std::endl;
std::cout << "what is the memory address?:" << std::endl;
std::cin >> input_;
unsigned int inp = char_to_pointer(input_);
std::cout << "imp: " << inp << std::endl;
Sleep(10000);
return 0;
}
int char_to_pointer(std::string input) {
return std::stoul(input, nullptr, 16);
}
My problem is that char_to_pointer only converts the hex string into a decimal.
this is what i want:
input: "0xc1f1"
output: 100
I found the solution:
#include <iostream>
#include <sstream>
#include <Windows.h>
#include <string>
int *char_to_pointer(std::string input);
int main() {
int sample = 100; // lets say this address is 0xc1f1
std::string input_;
std::cout << "addr:" << &sample << std::endl;
std::cout << "what is the memory address?:" << std::endl;
std::cin >> input_;
int *inp = char_to_pointer(input_);
std::cout << "imp: " << inp << std::endl;
std::cout << "imp*: " << *inp << std::endl;//This was my solution
std::cout << "imp&: " << &inp << std::endl;
Sleep(10000);
return 0;
}
int *char_to_pointer(std::string input) {
return (int *)std::stoul(input, nullptr, 16);
}
I have been looking into a problem whereby I am converting a float to a human readable format, and back. Namely a string. I have ran into issues using stringstream and found that atof produces "better" results.
Notice, I do not print out the data in this case, I used the debugger to retrieve the values:
const char *val = "73.31";
std::stringstream ss;
ss << val << '\0';
float floatVal = 0.0f;
ss >> floatVal; //VALUE IS 73.3100052
floatVal = atof(val); //VALUE IS 73.3099976
There is probably a reasonable explanation to this. If anybody can enlighten me I'd be greatful :).
Answer is based on the assumption that OP uses MSVC
atof is indeed better in reading floating point values than istream.
See this example:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib>
int main()
{
const char *val = "73.31";
std::stringstream ss;
ss << val;
float floatVal = 0.0f;
ss >> floatVal;
std::cout << "istream>>(float&) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
double doubleVal = atof(val);
std::cout << "double atof(const char*) :" << std::setw(18) << std::setprecision(15) << doubleVal << std::endl;
floatVal = doubleVal;
std::cout << "(float)double atof(const char*) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
doubleVal = floatVal;
std::cout << "(double)(float)double atof(const char*) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
}
Output:
istream>>(float&) : 73.3100051879883
double atof(const char*) : 73.31
(float)double atof(const char*) : 73.3099975585938
(double)(float)double atof(const char*) : 73.3099975585938
The compiler even warns about the conversion from doubleto float this:
warning C4244: '=': conversion from 'double' to 'float', possible loss of data
I also found this page: Conversions from Floating-Point Types
Update:
The value 73.3099975585938 seems to be the correct float interpretation of the double value 73.31.
Update:
istream>>(double&) works correctly as well:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib>
int main()
{
const char *val = "73.31";
std::stringstream ss;
ss << val;
double doubleVal = 0.0f;
ss >> doubleVal;
std::cout << "istream>>(double&) :" << std::setw(18) << std::setprecision(15) << doubleVal << std::endl;
}
Output:
istream>>(double&) : 73.31
For arithmetic types istream::operator>> uses num_get::get.
num_get::get should be using something like scanf("%g") for float source
BUT:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <iomanip>
#include <cstdlib>
int main()
{
std::string s = "73.31";
float f = 0.f;
sscanf(s.c_str(), "%g", &f);
std::cout << std::setw(18) << std::setprecision(15) << f << std::endl;
}
Output:
73.3099975585938
For me this looks like there might be a bug in Microsoft num_get
I am trying to solve the relatively simple problem of being able to write a double to a file and then to read the file into a double again. Based on this answer I decided to use the human readable format.
I have successfully circumvented the problems some compilers have with nan and [-]infinity according to this question. With finite numbers I use the std::stod function to convert the string representation of a number into the number itself. But from time to time the parsing fails with numbers close to zero, such as in the following example:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
stream << small;
std::cout << "serialized: " << stream.str() << std::endl;
double out = std::stod(stream.str());
std::cout << "de-serialized: " << out << std::endl;
return 0;
}
On my machine the result is:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
terminate called after throwing an instance of 'std::out_of_range'
what(): stod
The program has unexpectedly finished.
That is, the number is too close to zero to be properly parsed. At first I thougth that the problem is that this number is denormal, but this doesn't seem to be the case, since the mantissa starts with a 9 and not a 0.
Qt on the other hand has no problems with this number:
#include <cmath>
#include <limits>
#include <QString>
#include <QTextStream>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
QString string = QString::number(small, 'g', maxPrecision);
QTextStream stream(stdout);
stream.setRealNumberPrecision(maxPrecision);
stream << "serialized: " << string << '\n';
bool ok;
double out = string.toDouble(&ok);
stream << "de-serialized: " << out << '\n' << (ok?"ok":"not ok") << '\n';
return 0;
}
Outputs:
serialized: 9.2263152681638151025201733115952403273156653201666065e-318
de-serialized: 9.2263152681638151025201733115952403273156653201666065e-318
ok
Summary:
Is this a bug in the gcc implementation of standard library?
Can I circumvent this elegantly?
Should I just use Qt?
Answering question #2:
This is probably my "C-way" kind of thinking, but you could copy the double into a uint64_t (mem-copying, not type-casting), serialize the uint64_t instead, and do the opposite on de-serialization.
Here is an example (without even having to copy from double into uint64_t and vice-versa):
uint64_t* pi = (uint64_t*)&small;
stringstream stream;
stream.precision(maxPrecision);
stream << *pi;
cout << "serialized: " << stream.str() << endl;
uint64_t out = stoull(stream.str());
double* pf = (double*)&out;
cout << "de-serialized: " << *pf << endl;
Please note that in order to avoid breaking strict-aliasing rule, you actually do need to copy it first, because the standard does not impose the allocation of double and uint64_t to the same address-alignment:
uint64_t ismall;
memcpy((void*)&ismall,(void*)&small,sizeof(small));
stringstream stream;
stream.precision(maxPrecision);
stream << ismall;
cout << "serialized: " << stream.str() << endl;
ismall = stoull(stream.str());
double fsmall;
memcpy((void*)&fsmall,(void*)&ismall,sizeof(small));
cout << "de-serialized: " << fsmall << endl;
If you're open to other recording methods you can use frexp:
#include <cmath>
#include <iostream>
#include <sstream>
#include <limits>
const std::size_t maxPrecision = std::numeric_limits<double>::digits;
const double small = std::exp(-730.0);
int main()
{
std::stringstream stream;
stream.precision(maxPrecision);
int exp;
double x = frexp(small, &exp);
//std::cout << x << " * 2 ^ " << exp << std::endl;
stream << x << " * 2 ^ " << exp;
int outexp;
double outx;
stream.seekg(0);
stream >> outx;
stream.ignore(7); // >> " * 2 ^ "
stream >> outexp;
//std::cout << outx << " * 2 ^ " << outexp << std::endl;
std::cout << small << std::endl << outx * pow(2, outexp) << std::endl;
return 0;
}
So... I want to create simple HTTP Chunked transfer encoding prototype. I have messages as std::strings. And my server API is all string based... so I wonder how to turn std::string length into hex and than back into string?
So say we had std::string("This is the data in the first chunk\r\n").length() that would return say int 37. I want to convert it into hex 0x25 and than to get out from that hex std::string("25"). How to do such thing (using stl and boost)?
#include <sstream>
#include <iomanip>
#include <iostream>
int main() {
// To string:
std::ostringstream oss;
oss << std::hex << 37;
std::string result = oss.str();
std::cout << result << '\n';
// Back from string (if you need it):
std::istringstream iss(result);
int original;
if (!(iss >> std::hex >> original)) {
// handle error here
} else {
std::cout << original << '\n';
}
}
std::stringstream buffer;
buffer << std::hex << your_number;
buffer.str() will now give you a hex-representation of your number; If you want the 0x before the number, use this:
buffer << std::hex << showbase << your_number;
#include <sstream>
#include <iomanip>
std::ostringstream str;
str << "0x" << std::hex << length;
std::string result = str.str();
Demonstrated here.
Stringstreams are one way:
std::ostringstream ss;
ss << "0x" << std::hex << 12345;
std::string aString = ss.str();
An alternative is the all-mighty boost::format.
This would be a solution:
std::string convert_length_to_hex(const std::string& str)
{
std::ostringstream result;
result << std::hex << str.length();
return result.str();
}
Here is my example of dec to hex conversion and then back
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
std::string dec2hex(int dec){
std::string result;
std::stringstream ss;
ss << std::hex << dec;
ss >> result;
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
return result;}
int hex2dec(std::string& hex){
int x;
std::stringstream ss;
ss << std::hex << hex;
ss >> x;
return x;
}
int main()
{
std::string hex = "ABCD";
int dec = hex2dec(hex);
std::cout << dec << std::endl;
std::cout << dec2hex(dec) << std::endl;
return 0;
}