Perpustakaan FAST_FLOAT menyediakan implementasi header yang cepat untuk fungsi C ++ From_Chars untuk float dan tipe double serta tipe integer. Fungsi -fungsi ini mengubah string ASCII yang mewakili nilai desimal (misalnya, 1.3e10 ) menjadi tipe biner. Kami menyediakan pembulatan yang tepat (termasuk putaran ke genap). Dalam pengalaman kami, fungsi fast_float ini berkali-kali lebih cepat daripada fungsi pembunuhan angka yang sebanding dari perpustakaan standar C ++ yang ada.
Secara khusus, fast_float menyediakan dua fungsi berikut untuk mengurai nomor poin floating dengan sintaks C ++ 17-seperti (pustaka itu sendiri hanya membutuhkan C ++ 11):
from_chars_result from_chars ( char const *first, char const *last, float &value, ...);
from_chars_result from_chars ( char const *first, char const *last, double &value, ...);Anda juga dapat mengurai tipe integer:
from_chars_result from_chars ( char const *first, char const *last, int &value, ...);
from_chars_result from_chars ( char const *first, char const *last, unsigned &value, ...); Tipe pengembalian ( from_chars_result ) didefinisikan sebagai struct:
struct from_chars_result {
char const *ptr;
std::errc ec;
}; Ini menguraikan urutan karakter [first, last) untuk angka. Ini mem-parsing bilangan titik mengambang yang mengharapkan format lokal-independen yang setara dengan fungsi C ++ 17 From_chars. Nilai titik mengambang yang dihasilkan adalah nilai titik mengambang terdekat (menggunakan float atau double ), menggunakan konvensi "putaran hingga bahkan" untuk nilai-nilai yang seharusnya jatuh tepat di antara dua nilai. Artinya, kami memberikan penguraian yang tepat sesuai dengan standar IEEE.
Diberi parse yang berhasil, pointer ( ptr ) dalam nilai yang dikembalikan diatur ke titik tepat setelah angka parsed, dan value yang dirujuk diatur ke nilai parsed. Dalam hal kesalahan, ec yang dikembalikan berisi kesalahan perwakilan, jika tidak, nilai default ( std::errc() ) disimpan.
Implementasi tidak melempar dan tidak mengalokasikan memori (misalnya, dengan new atau malloc ).
Ini akan mengurai nilai tak terbatas dan NAN.
Contoh:
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " 3.1416 xyz " ;
double result;
auto answer = fast_float::from_chars (input. data (), input. data () + input. size (), result);
if (answer. ec != std::errc ()) { std::cerr << " parsing failure n " ; return EXIT_FAILURE; }
std::cout << " parsed the number " << result << std::endl;
return EXIT_SUCCESS;
}Anda dapat mengurai angka yang dibatasi:
std::string input = " 234532.3426362,7869234.9823,324562.645 " ;
double result;
auto answer = fast_float::from_chars(input.data(), input.data() + input.size(), result);
if (answer.ec != std::errc()) {
// check error
}
// we have result == 234532.3426362.
if (answer.ptr[ 0 ] != ' , ' ) {
// unexpected delimiter
}
answer = fast_float::from_chars(answer.ptr + 1 , input.data() + input.size(), result);
if (answer.ec != std::errc()) {
// check error
}
// we have result == 7869234.9823.
if (answer.ptr[ 0 ] != ' , ' ) {
// unexpected delimiter
}
answer = fast_float::from_chars(answer.ptr + 1 , input.data() + input.size(), result);
if (answer.ec != std::errc()) {
// check error
}
// we have result == 324562.645. Seperti standar C ++ 17, fungsi fast_float::from_chars mengambil argumen terakhir opsional dari tipe fast_float::chars_format . Ini adalah nilai bitset: Kami memeriksa apakah fmt & fast_float::chars_format::fixed dan fmt & fast_float::chars_format::scientific diatur untuk menentukan apakah kami masing -masing mengizinkan titik tetap dan notasi ilmiah. Standarnya adalah fast_float::chars_format::general yang memungkinkan baik fixed dan scientific .
Perpustakaan berupaya mengikuti spesifikasi C ++ 17 (lihat 28.2.3. (6.1)).
from_chars tidak melewatkan karakter ruang putih terkemuka (kecuali fast_float::chars_format::chars_format diatur).+ terkemuka dilarang (kecuali fast_float::chars_format::skip_white_space diatur).float dan tipe double ). Kami mencari nilai terdekat. Kami berputar ke mantissa bahkan ketika kami berada di antara dua bilangan titik terapung biner.Selain itu, kami memiliki batasan berikut:
float dan double , tapi tidak long double . Kami juga mendukung tipe poin-floating-point fixed-width seperti std::float32_t dan std::float64_t .1e9999 ), kami mewakili itu menggunakan nilai tak terbatas infinity atau negatif dan ec yang dikembalikan diatur ke std::errc::result_out_of_range .Kami mendukung Visual Studio, MacOS, Linux, FreeBSD. Kami mendukung endian besar dan kecil. Kami mendukung sistem 32-bit dan 64-bit.
Kami berasumsi bahwa mode pembulatan diatur ke terdekat ( std::fegetround() == FE_TONEAREST ).
Anda juga dapat menguraikan tipe integer menggunakan basis yang berbeda (misalnya, 2, 10, 16). Kode berikut akan mencetak nomor 22250738585072012 tiga kali:
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
uint64_t i;
std::string str = " 22250738585072012 " ;
auto answer = fast_float::from_chars (str. data (), str. data () + str. size (), i);
if (answer. ec != std::errc ()) {
std::cerr << " parsing failure n " ;
return EXIT_FAILURE;
}
std::cout << " parsed the number " << i << std::endl;
std::string binstr = " 1001111000011001110110111001001010110100111000110001100 " ;
answer = fast_float::from_chars (binstr. data (), binstr. data () + binstr. size (), i, 2 );
if (answer. ec != std::errc ()) {
std::cerr << " parsing failure n " ;
return EXIT_FAILURE;
}
std::cout << " parsed the number " << i << std::endl;
std::string hexstr = " 4f0cedc95a718c " ;
answer = fast_float::from_chars (hexstr. data (), hexstr. data () + hexstr. size (), i, 16 );
if (answer. ec != std::errc ()) {
std::cerr << " parsing failure n " ;
return EXIT_FAILURE;
}
std::cout << " parsed the number " << i << std::endl;
return EXIT_SUCCESS;
} Saat mem-parsing nilai titik mengambang, angka-angka kadang-kadang bisa terlalu kecil (misalnya, 1e-1000 ) atau terlalu besar (misalnya, 1e1000 ). Bahasa C menetapkan preseden bahwa nilai -nilai kecil ini di luar jangkauan. Dalam kasus seperti itu, adalah kebiasaan untuk menguraikan nilai -nilai kecil ke nol dan nilai besar hingga tak terbatas. Itulah perilaku bahasa C (misalnya, stdtod ). Itulah perilaku yang diikuti oleh Perpustakaan Fast_Float.
Secara khusus, kami mengikuti interpretasi standar Jonathan Wakely:
Bagaimanapun, nilai yang dihasilkan adalah salah satu dari paling banyak dua nilai titik mengambang yang paling dekat dengan nilai string yang sesuai dengan pola.
Ini juga pendekatan yang diambil oleh Perpustakaan Microsoft C ++.
Oleh karena itu, kami memiliki contoh berikut:
double result = - 1 ;
std::string str = " 3e-1000 " ;
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
// r.ec == std::errc::result_out_of_range
// r.ptr == str.data() + 7
// result == 0 double result = - 1 ;
std::string str = " 3e1000 " ;
auto r = fast_float::from_chars(str.data(), str.data() + str.size(), result);
// r.ec == std::errc::result_out_of_range
// r.ptr == str.data() + 6
// result == std::numeric_limits<double>::infinity() Pengguna yang menginginkan nilai dibiarkan tidak dimodifikasi dengan std::errc::result_out_of_range dapat melakukannya dengan menambahkan dua baris kode:
double old_result = result; // make copy
auto r = fast_float::from_chars(start, end, result);
if (r.ec == std::errc::result_out_of_range) { result = old_result; } Dalam C ++ 20, Anda dapat menggunakan fast_float::from_chars untuk parse string pada waktu kompilasi, seperti dalam contoh berikut:
// consteval forces compile-time evaluation of the function in C++20.
consteval double parse (std::string_view input) {
double result;
auto answer = fast_float::from_chars (input. data (), input. data () + input. size (), result);
if (answer. ec != std::errc ()) { return - 1.0 ; }
return result;
}
// This function should compile to a function which
// merely returns 3.1415.
constexpr double constexptest () {
return parse ( " 3.1415 input " );
} Perpustakaan juga mendukung tipe poin floating-lebar tetap seperti std::float32_t dan std::float64_t . Misalnya, Anda bisa menulis:
std:: float32_t result;
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);Kami juga mendukung input UTF-16 dan UTF-32, serta ASCII/UTF-8, seperti dalam contoh berikut:
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::u16string input = u" 3.1416 xyz " ;
double result;
auto answer = fast_float::from_chars (input. data (), input. data () + input. size (), result);
if (answer. ec != std::errc ()) { std::cerr << " parsing failure n " ; return EXIT_FAILURE; }
std::cout << " parsed the number " << result << std::endl;
return EXIT_SUCCESS;
} Standar C ++ menetapkan bahwa from_chars harus independen lokal. Secara khusus, pemisah desimal harus periode ( . ). Namun, beberapa pengguna masih ingin menggunakan pustaka fast_float dengan cara yang bergantung pada lokal. Menggunakan fungsi terpisah yang disebut from_chars_advanced , kami memungkinkan pengguna untuk melewati instance parse_options yang berisi pemisah desimal khusus (misalnya, koma). Anda dapat menggunakannya sebagai berikut.
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " 3,1416 xyz " ;
double result;
fast_float::parse_options options{fast_float::chars_format::general, ' , ' };
auto answer = fast_float::from_chars_advanced (input. data (), input. data () + input. size (), result, options);
if ((answer. ec != std::errc ()) || ((result != 3.1416 ))) { std::cerr << " parsing failure n " ; return EXIT_FAILURE; }
std::cout << " parsed the number " << result << std::endl;
return EXIT_SUCCESS;
}# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " 1d+4 " ;
double result;
fast_float::parse_options options{fast_float::chars_format::fortran};
auto answer = fast_float::from_chars_advanced (input. data (), input. data () + input. size (), result, options);
if ((answer. ec != std::errc ()) || ((result != 10000 ))) { std::cerr << " parsing failure n " ; return EXIT_FAILURE; }
std::cout << " parsed the number " << result << std::endl;
return EXIT_SUCCESS;
}# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " +.1 " ; // not valid
double result;
fast_float::parse_options options{fast_float::chars_format::json};
auto answer = fast_float::from_chars_advanced (input. data (), input. data () + input. size (), result, options);
if (answer. ec == std::errc ()) { std::cerr << " should have failed n " ; return EXIT_FAILURE; }
return EXIT_SUCCESS;
} Secara default, format JSON tidak mengizinkan inf :
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " inf " ; // not valid in JSON
double result;
fast_float::parse_options options{fast_float::chars_format::json};
auto answer = fast_float::from_chars_advanced (input. data (), input. data () + input. size (), result, options);
if (answer. ec == std::errc ()) { std::cerr << " should have failed n " ; return EXIT_FAILURE; }
return EXIT_SUCCESS;
} Anda dapat mengizinkannya dengan varian json_or_infnan yang tidak standar:
# include " fast_float/fast_float.h "
# include < iostream >
int main () {
std::string input = " inf " ; // not valid in JSON but we allow it with json_or_infnan
double result;
fast_float::parse_options options{fast_float::chars_format::json_or_infnan};
auto answer = fast_float::from_chars_advanced (input. data (), input. data () + input. size (), result, options);
if (answer. ec != std::errc () || (! std::isinf (result))) { std::cerr << " should have parsed infinity n " ; return EXIT_FAILURE; }
return EXIT_SUCCESS;
}Perpustakaan Fast_Float adalah bagian dari:
from_chars di GCC bergantung pada FAST_FLOAT,Algoritma FastFloat adalah bagian dari perpustakaan standar LLVM. Ada bagian implementasi yang diturunkan dari Adacore.
Perpustakaan Fast_Float memberikan kinerja yang mirip dengan perpustakaan FEEP_Double_Parser tetapi menggunakan algoritma yang diperbarui yang dikerjakan ulang dari bawah ke atas, dan sambil menawarkan API lebih sesuai dengan harapan programmer C ++. Perpustakaan Fast_Double_Parser adalah bagian dari kerangka belajar mesin Microsoft LightGBM.
rcppfastfloat .fast-float-rust .FastDoubleParser . Ini digunakan untuk sistem penting seperti Jackson.csFastFloat . Ini dapat mengurai bilangan titik mengambang acak dengan kecepatan 1 GB/s pada beberapa sistem. Kami menemukan bahwa seringkali dua kali lebih cepat dari pesaing terbaik yang tersedia, dan berkali-kali lebih cepat daripada banyak implementasi standar-perpustakaan.
$ ./build/benchmarks/benchmark
# parsing random integers in the range [0,1)
volume = 2.09808 MB
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/sLihat https://github.com/lemire/simple_fastfloat_benchmark untuk kode pembandingan kami.
Perpustakaan ini hanya tajuk berdasarkan desain. File CMake menyediakan target fast_float yang hanya merupakan pointer ke direktori include .
Jika Anda menjatuhkan repositori fast_float dalam proyek cmake Anda, Anda harus dapat menggunakannya dengan cara ini:
add_subdirectory (fast_float)
target_link_libraries (myprogram PUBLIC fast_float)Atau Anda mungkin ingin mengambil ketergantungan secara otomatis jika Anda memiliki versi CMAKE yang cukup baru (3.11 atau lebih dari yang lebih baik):
FetchContent_Declare(
fast_float
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
GIT_TAG tags/v6.1.6
GIT_SHALLOW TRUE )
FetchContent_MakeAvailable(fast_float)
target_link_libraries (myprogram PUBLIC fast_float) Anda harus mengubah garis GIT_TAG sehingga Anda memulihkan versi yang ingin Anda gunakan.
Anda juga dapat menggunakan CPM, seperti itu:
CPMAddPackage(
NAME fast_float
GITHUB_REPOSITORY "fastfloat/fast_float"
GIT_TAG v6.1.6) script/amalgamate.py dapat digunakan untuk menghasilkan versi header tunggal dari perpustakaan jika diinginkan. Cukup jalankan skrip dari direktori root repositori ini. Anda dapat menyesuaikan jenis lisensi dan file output jika diinginkan seperti yang dijelaskan dalam Bantuan Baris Perintah.
Anda dapat langsung mengunduh file header tunggal yang dihasilkan secara otomatis:
https://github.com/fastfloat/fast_float/releases/download/v7.0.0/fast_float.h
fast_float-devel ). Meskipun pekerjaan ini terinspirasi oleh banyak orang yang berbeda, karya ini mendapat manfaat terutama dari pertukaran dengan Michael Eisel, yang memotivasi penelitian asli dengan wawasan kuncinya, dan dengan Nigel Tao yang memberikan umpan balik yang tak ternilai. Rémy Oudompheng pertama kali menerapkan jalur cepat yang kami gunakan dalam kasus digit panjang.
Perpustakaan termasuk kode yang diadaptasi dari Google Wuffs (ditulis oleh Nigel Tao) yang awalnya diterbitkan di bawah lisensi Apache 2.0.