転載元(英語原稿):
https://lemire.me/blog/2020/09/10/parsing-floats-in-c-benchmarking-strtod-vs-from_chars/
プログラマーは、文字列を浮動小数点数に変換する必要があることがよくあります。たとえば、文字列「3.1416」を取得し、結果の値を浮動小数点型として取得したい場合があります。
C/C++では、標準的な方法はstrtod関数です。
char * string = "3.1416";
char * string_end = string;
double x = strtod(string, &string_end);
if(string_end == string) {
//you have an error!
}
残念ながら、strtod関数は、これらの文字列処理関数の多くと同様に、ロケールに依存します。これは、コードを実行するシステムによって動作が異なる可能性があることを意味します。ただし、すべてのランタイムライブラリには、strtod_lや_strtod_l(Windows)などのロケール固有の関数があるようです。これらのロケール固有の関数を使用して、デフォルトのロケールを指定し、すべてのシステムで同じように動作する関数を取得できます。
strtod関数の優れた機能の1つは、解析された数値の最後にポインターを返すことです。このようにして、たとえば、コンマ区切りの数値のシーケンスを効率的に解析できます。
C++ストリームを使用することもできますが、通常はパフォーマンスを対象としていません。
C++17では、より優れたオプションであるfrom_chars関数が提供されました。同様に機能します。
std::string st = "3.1416";
double x;
auto [p, ec] = std::from_chars(st.data(), st.data() + st.size(), x);
if (p == st.data()) {
//you have an errors!
}
ている点は、定義上、ロケールに依存しないことです。さらに、標準化されているため、どこでも利用できるはずです。残念ながら、私の知る限り、完全に実装されたfrom_chars関数が付属しているC ++コンパイラはVisualStudio2019だけです。最新のリリースが必要です。
確かに、C++17はしばらくの間リリースされており、多くのコンパイラがそれを完全にサポートしていると主張していますが、ランタイムライブラリは追いつく必要があります!もちろん、独立したfrom_chars実装を取得することもできますが、ランタイムライブラリがC ++ 17をすぐにサポートしてくれると便利です。
それでも、マイクロソフトが正しいことを行い、最新の標準を熱心にサポートしていることを祝う必要があります。
Visual Studiofrom_charsについて良いことを聞きました。そしてとりわけ、それは非常に速いということです。
もっと早く知りたかった。だから私はベンチマークを書きました![0,1]間隔で多数のランダム値を生成し、それらを解析して戻すのにかかる時間を記録します。
|stdtod(C)|120MB/s|
|::|::|
|from_chars(C++17)|140MB/s|
コストをかけずに、パフォーマンスが20%向上します。素晴らしい。