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:
-
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 forvar_export()
. -
Support for * width and precision, in which case the width/precision is
provided as an argument toprintf()
. This is a feature ofprintf()
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
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
ofprintf()
specifiers.The proposed improvements are:
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 forvar_export()
.Support for * width and precision, in which case the width/precision is
provided as an argument toprintf()
. This is a feature ofprintf()
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
Seems like a no-brainer to add on my side.
Best regards
George P. Banyard
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
ofprintf()
specifiers.The proposed improvements are:
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 forvar_export()
.Support for * width and precision, in which case the width/precision is
provided as an argument toprintf()
. This is a feature ofprintf()
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,
NikitaSeems like a no-brainer to add on my side.
Best regards
George P. Banyard
Any further feedback on this? Otherwise I'll merge these printf()
improvements.
Nikita