Hi internals,

I'd like to make two improvements to the printf() functionality exposed by
PHP (also affecting other variations like sprintf, vprintf, etc.) These
improvements are motivated by
https://wiki.php.net/rfc/locale_independent_float_to_string, which will
make float to string casts locale insensitive, but not change the behavior
of printf() specifiers.

The proposed improvements are:

1. Support for the %h and %H specifiers, which behave the same as %g and
%G, but are locale insensitive. These specifiers are already supported
internally in PHP (though %h goes by the name of %k for reasons that are
not relevant to userland) and is used for formatting floating-point numbers
where case-sensitivity is not desired, such as for var_export().

2. Support for * width and precision, in which case the width/precision is
provided as an argument to printf(). This is a feature of printf() in C.

The combination of these two features allows us to easily print floating
point numbers exactly as PHP would print them:

    // Locale-sensitive using precision ini setting.
    sprintf("%.*G", ini_get('precision'), $float);

    // Locale-insensitive using serialize_precision ini setting.
    sprintf("%.*H", ini_get('serialize_precision'), $float);

Notably, this also supports precision -1 (the default serialize_precision),
which will pick the shortest accurate representation of the float.

Without these features, it is actually quite hard to replicate PHP's exact
behavior. The best approximation I've found is to print with %G at multiple
precisions, pick out the shorted one and replace commas with dots on the
assumption that comma is the only locale-specific decimal separator. It
would be good to expose what PHP can already do directly.

Implementations for the two features are available at
https://github.com/php/php-src/pull/5432 and
https://github.com/php/php-src/pull/5436.

Regards,
Nikita

Reply via email to