Search code examples
c++type-conversionc++17character

C++ std::from_chars is ignoring expontens <10


I am trying to convert strings to double with std::from_chars, but I cannot get alignment with strtod when it comes to exponential numbers. The reproducer:

#include <string>
#include <iostream>
#include <charconv>
void xxx(std::string const A){
  double x;
  std::from_chars(&A[0],&A.back(),x,std::chars_format::scientific);
  printf("%s,%.17g\n",A.c_str(),x);
}
void yyy(std::string const A){
  printf("%s,%.17g\n",A.c_str(),strtod(&A[0],NULL));
}

int main(){
  xxx(std::string("0.9226e-01"));
  yyy(std::string("0.9226e-01"));
  xxx(std::string("0.9226e-10"));
  yyy(std::string("0.9226e-10"));
}

which produces output

0.9226e-01,0.92259999999999998
0.9226e-01,0.092259999999999995
0.9226e-10,0.092259999999999995
0.9226e-10,9.226e-11

I would say that strtod produces the correct results.

Happy to learn that I got it wrong.

Platform: linux g++ version: 12.2

Thanks and merry christmas


Solution

  • Analyzes the character sequence [first,last) for a pattern described below.

    The closing parenthesis means last is excluded. Thus, the actual data that std::from_chars(&A[0], &A.back(), ...) is processing are

    "0.9226e-0"
    "0.9226e-1"
    

    The correct invocation:

    void xxx(std::string const A){
      double x;
      std::from_chars(A.begin(), A.end(), x,std::chars_format::scientific);
      printf("%s,%.17g\n", A.c_str(),x);
    }
    

    or

    void xxx(std::string const A){
      double x;
      std::from_chars(&A[0], &A[0] + A.size(), x,std::chars_format::scientific);
      printf("%s,%.17g\n", A.c_str(),x);
    }