Use strtof() and not strtod() for float4 input

Enterprise / PostgreSQL - Andrew Gierth [postgresql.org] - 13 February 2019 15:19 EST

Using strtod() creates a double-rounding problem; the input decimal
value is first rounded to the nearest double; rounding that to the nearest float may then give an incorrect result.

An example is that 7.038531e-26 when input via strtod and then rounded to float4 gives 0xAE43FEp-107 instead of the correct 0xAE43FDp-107.

Values output by earlier PG versions with extra_float_digits=3 should all be read in with the same values as previously. However, values supplied by other software using shortest representations could be mis-read.

On platforms that lack a strtof() entirely, we fall back to the old incorrect rounding behavior. (As strtof() is required by C99, such platforms are considered of primarily historical interest.) On VS2013, some workarounds are used to get correct error handling.

The regression tests now test for the correct input values, so platforms that lack strtof() will need resultmap entries. An entry for HP-UX 10 is included (more may be needed).

f397e08599 Use strtof() and not strtod() for float4 input.
configure | 13 +
configure.in | 1 +
src/backend/utils/adt/float.c | 56 ++-
src/include/pg_config.h.in | 3 +
src/include/pg_config.h.win32 | 3 +
src/include/port.h | 4 +
src/include/port/win32_port.h | 12 +
src/port/strtof.c | 123 ++++++
.../regress/expected/float4-misrounded-input.out | 436 +++++++++++++++++++++
src/test/regress/expected/float4.out | 136 ++++++-
src/test/regress/resultmap | 1 +
src/test/regress/sql/float4.sql | 37 ++
src/tools/msvc/Mkvcbuild.pm | 2 +
13 files changed, 810 insertions(+), 17 deletions(-)

Upstream: git.postgresql.org


  • Share