Reputation: 367
I am generating a text file to be used as a FORTRAN input file. The FORTRAN program specifies that the values it reads must be in a format such that
1.0
must be printed as
0.1000000E+01
As of right now the closest I have gotten in using iostream is
1.000000E+00
with the code
cout << setprecision(6) << fixed << scientific << uppercase;
_set_output_format(_TWO_DIGIT_EXPONENT);
cout << 1.0 << endl;
Does anyone know the best way to get a leading zero as shown above, preferably using ostream instead of printf?
Upvotes: 2
Views: 3066
Reputation: 101
Here is a solution using C++20 <format>. It hasn't rounding errors and you don't need to modify yor locale.
std::string scileading0(float number, unsigned short prec)
{
std::string str = std::vformat("{:." + std::to_string(prec-1) + "E}", std::make_format_args(number));
int deg = std::stoi(str.substr(str.find_first_of('E') + 1)) + 1;
return "0." + str.substr(0, 1) + str.substr(2, prec) + std::format("{:+}", deg).substr(0, 1) + std::format("{:0>2}", abs(deg));
}
Upvotes: 0
Reputation: 33046
As I said, what you ask is non-standard, but you can achieve that with a trick:
#include <iostream>
#include <iomanip>
#include <cmath>
class Double {
public:
Double(double x): value(x) {}
const double value;
};
std::ostream & operator<< (std::ostream & stream, const Double & x) {
// So that the log does not scream
if (x.value == 0.) {
stream << 0.0;
return stream;
}
int exponent = floor(log10(std::abs(x.value)));
double base = x.value / pow(10, exponent);
// Transform here
base /= 10;
exponent += 1;
stream << base << 'E' << exponent; // Change the format as needed
return stream;
}
int main() {
// Use it like this
std::cout << std::setprecision(6) << std::fixed;
std::cout << Double(-2.203e-15) << std::endl;
return 0;
}
The Double
wrapper is needed because you cannot redefine <<
for double
.
I did not test that way of separating exponent
and base
against the odds of floating point, maybe you can come up with a better alternative, but you get the idea :)
Upvotes: 1
Reputation: 119877
cout << "0." << setprecision(6) << fixed << scientific << uppercase << number * 10;
Upvotes: 1
Reputation: 153458
C thought:
Not a great answer because C++ answer preferred.
char buf[20];
buf[0] = ' ';
double x = -1.234567;
sprintf(&buf[1], "% .6E", x*10);
if (buf[3] == '.') { // detect if x was INF or NAN
buf[0] = buf[1];
buf[1] = '0';
buf[3] = buf[2];
buf[2] = '.';
}
// Cope with leading potential space if needed
if (buf[0] == ' ') memmove(&buf[0], &buf[1], strlen(buf));
printf("%s\n", buf);
// -0.1234567E+00
Weakness: Trouble if decimal point is not '.' or x near INF.
Upvotes: 1