以科学格式打印double,没有整数部分

时间:2015-06-15 10:32:34

标签: c double scientific-notation

一个简单的问题,但我无法获得有关这种格式的文档:我想用Fortran科学记数法打印一个浮点数,其整数部分始终为零。

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

我想像这样打印:

 .27460E+03

如何让这个结果尽可能干净?

5 个答案:

答案 0 :(得分:1)

我尝试使用log10()pow()执行此操作,但最终出现了舍入错误的问题。因此,正如@Karoly Horvath所评论的那样,字符串操作可能是最好的方法。

#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 :(得分:1)

如果您只关心整数部分为0并且没有真正遗漏0,即如果您使用0.27460E+03而不是.27460E+03就可以了做类似的事情:

#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);
}

否则你必须绕道而行。请注意,上面的代码只是为了让您入门。它肯定不会处理任何涉及的案件。

答案 2 :(得分:1)

字符串操作方法:

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
}

这将为|x| > DBL_MAX/10

打印“INF”

答案 3 :(得分:1)

sprintf()使用某种特殊格式无法一步完成OP的目标。使用#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; } 形成初始文本结果是一个很好的第一步,在尝试使用字符串操作进行“数学”时必须小心。

类似于@user3121023已删除的答案。

{{1}}

答案 4 :(得分:0)

fortran移植时遇到相同的问题。 未找到标准C格式的DId :( 实现了两种方法-使用log10 / pow和使用字符串操作。

#include <ansi_c.h>
#define BUFFL  16    

// using log10 , 3 digits after "."
char* fformat1(char* b, double a) {
int sign = 1;
double mant;              
double order;
int ord_p1;

if (a<0) {  
        sign =-1;
        a = -a;
    }
order=log10 (a);
if (order >=0) ord_p1 = (int) order +1; // due sto property of int
    else       ord_p1 = (int) order;

mant=a/(pow(10,ord_p1));

sprintf(b,"%.3fE%+03d",mant,ord_p1);

if (sign==-1) b[0]='-';
return b;      
}


// using string manipulation
char* fformat2(char* b, double a) {;    
int sign = 1;
int i;
int N=3;

if (a<0) {  
        sign =-1;
        a = -a;
    }

sprintf(b,"%0.3E",a*10); // remember - we *10 to have right exponent

b[1]=b[0];              // 3.123 => .3123 
b[0]='.';
for (i=N; i>=0; i--)        // and shif all left
    b[i+1]=b[i];
b[0]='0';               // pad with zero   0.312            
if (sign==-1) b[0]='-';  // sign if needed
return b;
}




int main () {
char b1[BUFFL];     // allocate buffer outside. 
char b2[BUFFL];
char b3[BUFFL];
char b4[BUFFL];   
char b5[BUFFL];   


printf("%s %s %s   %s %s \n", fformat(b1,3.1), fformat(b2,-3.0), fformat(b3,3300.), 
        fformat(b4,0.03), fformat(b5,-0.000221));

printf("%s %s %s   %s %s \n", fformat2(b1,3.1), fformat2(b2,-3.0), fformat2(b3,3300.), 
        fformat2(b4,0.03), fformat2(b5,-0.000221));


return 1;

}