2015-06-15 9 views
5

Prosty problem, ale nie mogę uzyskać dokumentacji dotyczącej tego rodzaju formatu: chcę wydrukować float w notacji naukowej Fortran, z jej całkowitą częścią zawsze równą zero.drukuj dwukrotnie w formacie naukowym bez części całkowitej.

printf("%0.5E",data); // Gives 2.74600E+02 

chcę wydrukować go tak:

.27460E+03 

Jak mogę uzyskać ten wynik jako czyste jak to możliwe?

+2

Potrzebuję nakarmić go do starego pliku wykonywalnego fortranu – avances123

+2

Manipulacja tekstem wydaje się być najlepszą drogą. Możesz szukać biblioteki, ale domyślam się, że nikt nie obsługuje tak dziwnego formatu. –

+4

https://www.google.com/search?q=c%2B%2B+print+fortran+format –

Odpowiedz

1

Próbowałem zrobić to z log10() i pow(), ale skończyło się na problemach z błędami zaokrąglania. Tak więc, jak komentuje @Karoly Horvath, manipulacja łańcuchami jest prawdopodobnie najlepszym podejściem.

#include <stdlib.h> 

char *fortran_sprintf_double(double x, int ndigits) { 
    char format[30], *p; 
    static char output[30]; 

    /* Create format string (constrain number of digits to range 1–15) */ 
    if (ndigits > 15) ndigits = 15; 
    if (ndigits < 1) ndigits = 1; 
    sprintf(format, "%%#.%dE", ndigits-1); 

    /* Convert number to exponential format (multiply by 10) */ 
    sprintf(output, format, x * 10.0); 

    /* Move the decimal point one place to the left (divide by 10) */ 
    for (p=output+1; *p; p++) { 
    if (*p=='.') { 
     *p = p[-1]; 
     p[-1] = '.'; 
     break; 
    } 
    } 

    return output; 
} 
1

Jeśli tylko dbać o części całkowitej będącej 0 i naprawdę nie opuszczając 0, czyli jeśli jesteś w porządku z 0.27460E+03 zamiast .27460E+03 mógłby zrobić coś podobnego do tego:

#include <stdio.h> 
#include <stdlib.h> 

void fortran_printf(); 

int main(void) 
{ 
     double num = 274.600; 
     fortran_printf(num); 

     exit(EXIT_SUCCESS); 
} 

void fortran_printf(double num) 
{ 
     int num_e = 0; 
     while (num > 1.0) { 
       num /= 10; 
       num_e++; 
     } 

     printf("%.5fE+%02d", num, num_e); 
} 

W przeciwnym razie musisz objechać przez ciągi. Zauważ, że powyższy kod ma tylko na celu rozpoczęcie pracy. Z pewnością nie zajmuje się żadnymi zaangażowanymi sprawami.

1

Ciąg podejście manipulacja:

int printf_NoIntegerPart(double x, int prec) { 
    char buf[20 + prec]; 
    sprintf(buf, "%+.*E", prec - 1, x * 10.0); // use + for consistent width output 
    if (buf[2] == '.') { 
    buf[2] = buf[1]; 
    buf[1] = '.'; 
    } 
    puts(buf); 
} 

int main(void) { 
    printf_NoIntegerPart(2.74600E+02, 5); // --> +.27460E+03 
} 

To będzie drukować "INF" dla |x| > DBL_MAX/10

1

printf() nie spełni cel OP w jednym kroku przy użyciu jakiegoś specjalnego formatu. Użycie sprintf() do utworzenia początkowego wyniku tekstowego jest dobrym pierwszym krokiem, należy zachować ostrożność podczas próby "matematycznego" manipulowania ciągami.

Usunięto odpowiedź z usuniętą odpowiedzią na @user3121023.

#include <assert.h> 
#include <stdlib.h> 
#include <stdio.h> 

int printf_NoIntegerPart(double x, int prec) { 
    assert(prec >= 2 && prec <= 100); 
    char buffer[prec + 16]; // Form a large enough buffer. 
    sprintf(buffer, "%.*E", prec - 1, x); 

    int dp = '.'; // Could expand code here to get current local's decimal point. 
    char *dp_ptr = strchr(buffer, dp); 
    char *E_ptr = strchr(buffer, 'E'); 
    // Insure we are not dealing with infinity, Nan, just the expected format. 
    if (dp_ptr && dp_ptr > buffer && E_ptr) { 
    // Swap dp and leading digit 
    dp_ptr[0] = dp_ptr[-1]; 
    dp_ptr[-1] = dp; 
    // If x was not zero … 
    if (x != 0) { 
     int expo = atoi(&E_ptr[1]); // Could use `strtol()` 
     sprintf(&E_ptr[1], "%+.02d", expo + 1); 
    } 
    } 
    return puts(buffer); 
} 

int main(void) { 
    printf_NoIntegerPart(2.74600E+02, 5); // ".27460E+03" 
    return 0; 
} 
Powiązane problemy