http://qs321.pair.com?node_id=11119929


in reply to A locale independent sprintf?

Is there an sprintf implementation available for Perl that is independent of any numeric locale settings?

Not that I know of.
The simple workaround is to write a perl sub that simply does a s/,/./ on what sprintf() returns.
Or are there additional locale settings that also need to be dealt with ?

Cheers,
Rob

Replies are listed 'Best First'.
Re^2: A locale independent sprintf?
by swl (Parson) on Jul 29, 2020 at 03:11 UTC

    Thanks Rob.

    I was using that strategy in my code, but it incurs sub overheads and profiling showed my uses were in a fairly hot path for large data sets. (It could also just another example of me micro-optimising, though).

      Using y/,/./, instead of s/,/./, should be faster (see "perlperf: Search and replace or tr"). Obviously, I can't say whether it will be noticeably or usefully faster.

      You may want the 'r' modifier. Here's a somewhat fudged example for demonstration purposes:

      $ perl -E 'say sprintf("3,%d", 14)' 3,14 $ perl -E 'say sprintf("3,%d", 14) =~ y/,/./' Can't modify constant item in transliteration (tr///) at -e line 1, at + EOF Execution of -e aborted due to compilation errors. $ perl -E 'say sprintf("3,%d", 14) =~ y/,/./r' 3.14

      If you try this, I'd be interested in what sort of speed improvement you see.

      — Ken

        Good point. I'll see if I can set up some benchmarking and post the results.

        Update:

        Running the code below under ubuntu bash under windows with LC_NUMERIC set to de_DE.iso88591 indicates that s///r is about 20% faster than y//r. Both are in the order of millions per second, though.

        And as yet another update, the order does switch between runs so it's not a consistent outcome.

        Results:

        de_DE.iso88591 3,1 3.1 3.1 Rate y_sprintf s_sprintf sprintf y_sprintf 4646523/s -- -19% -63% s_sprintf 5721423/s 23% -- -54% sprintf 12396265/s 167% 117% --

        Code:

        use Benchmark qw {:all}; use 5.016; local $| = 1; use POSIX qw /locale_h/; use locale; print POSIX::setlocale(LC_NUMERIC) . "\n"; my $x; $x = sprintf "%.2g", 3.14; print "$x\n"; $x = sprintf ("%.2g", 3.14) =~ y/,/./r; print "$x\n"; $x = sprintf ("%.2g", 3.14) =~ s/,/./r; print "$x\n"; cmpthese ( -3, { sprintf => 'use strict; use warnings; my $x = sprintf ("%.2g +", 3.14)', y_sprintf => 'use strict; use warnings; my $x = sprintf ("%.2g +", 3.14) =~ y/,/./r', s_sprintf => 'use strict; use warnings; my $x = sprintf ("%.2g +", 3.14) =~ s/,/./r', } );

        (post was further updated to distinguish results from code)