The following two files represent two ways to convert string to double considering locale.
strtod_fast.c
uses standard C runtime functionstrtod_slow.c
uses a hand written implementation
I experiment the code on 3 compilers
- MinGW-UCRT in msys2
$ gcc -v
Using built-in specs.
COLLECT_GCC=D:\msys64\ucrt64\bin\gcc.exe
COLLECT_LTO_WRAPPER=D:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/12.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-12.1.0/configure --prefix=/ucrt64 --with-local-prefix=/ucrt64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/ucrt64/include --libexecdir=/ucrt64/lib --enable-bootstrap --enable-checking=release --with-arch=x86-64 --with-tune=generic --enable-languages=c,lto,c++,fortran,ada,objc,obj-c++,jit --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts --enable-libstdcxx-time --disable-libstdcxx-pch --enable-lto --enable-libgomp --disable-multilib --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/ucrt64 --with-mpfr=/ucrt64 --with-mpc=/ucrt64 --with-isl=/ucrt64 --with-pkgversion='Rev2, Built by MSYS2 project' --with-bugurl=https://github.com/msys2/MINGW-packages/issues --with-gnu-as --with-gnu-ld --disable-libstdcxx-debug --with-boot-ldflags=-static-libstdc++ --with-stage1-ldflags=-static-libstdc++
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.1.0 (Rev2, Built by MSYS2 project)
Compiled with
$ gcc -O2 strtod_fast.c -o fast.exe
$ gcc -O2 strtod_slow.c -o slow.exe
Result:
$ ./fast.exe 3.1415926
elapsed time: 0.156250
fv = 3.142, dv=3.142
$ ./slow.exe 3.1415926
elapsed time: 0.562500
fv = 3.142, dv=3.142
$ ./fast.exe 0x1p12
elapsed time: 0.046875
fv = 4096.000, dv=4096.000
$ ./slow.exe 0x1p12
elapsed time: 0.250000
fv = 4096.000, dv=4096.000
- MinGW-MSVCRT(MinGW64) in msys2
$ gcc -v
Using built-in specs.
COLLECT_GCC=D:\msys64\mingw64\bin\gcc.exe
COLLECT_LTO_WRAPPER=D:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-12.1.0/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/include --libexecdir=/mingw64/lib --enable-bootstrap --enable-checking=release --with-arch=x86-64 --with-tune=generic --enable-languages=c,lto,c++,fortran,ada,objc,obj-c++,jit --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts --enable-libstdcxx-time --disable-libstdcxx-pch --enable-lto --enable-libgomp --disable-multilib --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-pkgversion='Rev2, Built by MSYS2 project' --with-bugurl=https://github.com/msys2/MINGW-packages/issues --with-gnu-as --with-gnu-ld --disable-libstdcxx-debug --with-boot-ldflags=-static-libstdc++ --with-stage1-ldflags=-static-libstdc++
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.1.0 (Rev2, Built by MSYS2 project)
Compiled with
$ gcc -O2 strtod_fast.c -o fast.exe
$ gcc -O2 strtod_slow.c -o slow.exe
Result:
$ ./fast.exe 3.1415926
elapsed time: 0.359375
fv = 3.142, dv=3.142
$ ./slow.exe 3.1415926
elapsed time: 0.531250
fv = 3.142, dv=3.142
$ ./fast.exe 0x1p12 (MSVCRT cannot parse 0x format floating point number at all!)
elapsed time: 0.062500
fv = 0.000, dv=0.000
$ ./slow.exe 0x1p12
elapsed time: 0.171875
fv = 4096.000, dv=4096.000
- Arch Linux on WSL2
❯ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/12.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror --with-build-config=bootstrap-lto --enable-link-serialization=1
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.1.0 (GCC)
Compiled with
$ gcc -O2 strtod_fast.c -o fast
$ gcc -O2 strtod_slow.c -o slow
Result:
❯ ./fast 3.1415926
elapsed time: 0.111824
fv = 3.142, dv=3.142
❯ ./slow 3.1415926
elapsed time: 0.131362
fv = 3.142, dv=3.142
❯ ./fast 0x1p12
elapsed time: 0.040000
fv = 4096.000, dv=4096.000
❯ ./slow 0x1p12
elapsed time: 0.064249
fv = 4096.000, dv=4096.000