Question

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?

Was it helpful?

Solution

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 :)

OTHER TIPS

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.

  1. Create a locale facet that prints NO decimal point, and imbue it.
  2. cout << "0." << setprecision(6) << fixed << scientific << uppercase << number * 10;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top