Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When converting a double to a string, what can the first string character be?

When converting a double to a string like so:

static void strfromdouble(char *buf, size_t n, double d) {
    snprintf(buf, n, "%.14g", d);
}

Which characters could end up in buf[0] after the call to snprintf?

Obviously, it could be one of the following: 0-9, -, . but since we are using floating point math here, there are probably more characters that could end up in buf[0] like I for Inf or N for NaN and maybe even more?

Is the behaviour of snprintf standardized in this situation across different compilers and platforms? If it is, where is the specification, i.e. where can I look up which characters my code would have to be able to deal with in buf[0]?

like image 881
Andreas Avatar asked Jan 28 '26 16:01

Andreas


1 Answers

When converting a double to a string, what can the first string character be?

Easy to generate "0123456789-+ iInN". But other char are possible, depending on how far we want to stretch it.

Obviously, it could be one of the following: 0-9, -, . but since we are using floating point math here, there are probably more characters that could end up in buf[0] like I for Inf or N for NaN and maybe even more?

snprintf(buf, n, "%.14g", d);

When n = 1, expect buf[0] == '\0'

When n = 0, expect buf[0] to be unchanged so any char value is possible there.

With "%.14g" I would not expect 'I' nor 'N', but 'i' and 'n'.
"%.14G" would produce 'I' and 'N'.
A leading '.' does not happen with this format.

With other locales, (research setlocale()), the '-' may be something else. I know of no locale that does that though.

Other formats

With other format "% something [gefaGefa]" strings:

The first character could be a space ' ' or '+'. Like '-', that can vary with locale.

If a leading '.' is possible (I am confident this is not possible with standard formats), others locales may use an alternate such as ','.


With implementation specific formats, any lead character is possible.

With invalid formats, any lead character is possible due to undefined behavior.


#include <stdio.h>

int main(void) {
  char s[1000];
  double inf = strtod("inf", 0);
  double nan = strtod("nan", 0);
  snprintf(s, sizeof s, "%g\n", 0.0);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%g\n", 9.0);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%g\n", -1.0);  printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%+g\n", +1.0); printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%g\n", inf);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%G\n", inf);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%g\n", nan);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%G\n", nan);   printf("%3d %.1s\n", s[0], s);
  snprintf(s, sizeof s, "%5g\n", 1.0);  printf("%3d %.1s\n", s[0], s);
  snprintf(s, 1, "%g\n", 1.0);          printf("%3d %.1s\n", s[0], s);
  s[0] = 'z';
  snprintf(s, 0, "%g\n", 1.0);          printf("%3d %.1s\n", s[0], s);
  return 0;
}

Output

 48 0
 57 9
 45 -
 43 +
105 i
 73 I
110 n
 78 N
 32  
  0 
122 z

Is the behaviour of snprintf standardized in this situation across different compilers and platforms?

Yes. Compliant possibilities include "0123456789-+ iInN". Some compilers may add additional implementation defined ones.


where is the specification (?)

Look for the C spec. Latest is C17

Where do I find the current C or C++ standard documents?


Details:

infinity --> [-]inf or [-]infinity (efga) or uppercase version (EFGA)
nan --> [-]nan or [-]nan(n-char-sequence) or uppercase prefix version

%f --> [−]ddd.ddd,if a decimal-point character appears,at least one digit appears before it.
%F --> like %f
%e --> [−]d.ddd e±dd
%e --> like %e, but with E
%g --> converted in style f or e
%G --> converted in style F or E
%a --> [−]0xh.hhhh p±d
%A --> like %a, but with X,P
like image 110
chux - Reinstate Monica Avatar answered Jan 30 '26 07:01

chux - Reinstate Monica



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!