Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: LC_NUMERIC=fr_FR and floating point arithmetics
- X-seq: zsh-workers 18330
- From: Oliver Kiddle <okiddle@xxxxxxxxxxx>
- To: Stephane CHAZELAS <Stephane_CHAZELAS@xxxxxxxx>
- Subject: Re: LC_NUMERIC=fr_FR and floating point arithmetics
- Date: Mon, 10 Mar 2003 09:58:20 +0100
- Cc: Zsh hackers list <zsh-workers@xxxxxxxxxx>
- In-reply-to: <20030224184502.A9922@xxxxxxxxxxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
- References: <20030224184502.A9922@xxxxxxxxxxxxxxxxxx>
On 24 Feb, Stephane CHAZELAS wrote:
> $ LC_NUMERIC=fr_FR ksh93 -c 'float a=1; echo $(( a / 3 ))'
> 0,333333333333
> $ LC_NUMERIC=fr_FR zsh -c 'float a=1; echo $(( a / 3 ))'
> 0,33333333333333331.
>
> zsh seems to assume that "." is the decimal separator which is
> not correct in a french locale.
>
> I agree this is confusing. A ksh93 script such as
> echo $(( 1. / 3 ))
>
> won't work under french locale.
> (must be echo $(( 1, / 3 )) )
Which is worse in my opinion. $(( 1.1 )) really ought to be interpreted
as a 1 point 1 regardless of locale - it is otherwise impossible to use
decimals in portable shell scripts.
If we didn't have backward and ksh compatibility to consider, I would
be inclined to say that $a for floats and $(( ... )) should always use
the C locale and anyone wanting locale specific output could use printf
(see below) (implementing this is easy; just save the LC_NUMERIC locale
in convfloat()).
But keeping locale handling in output means that scalar parameters
can't be reused in a calculation. And making math evaluation accept
either `.' or whatever the locale dictates is not easy when you
consider that a comma in math evaluation is used as a separator:
(( a=1, 3.4 ))
Also, because we allow this:
% a='3 + 4'
% echo $(( a ))
7
you can't just interpret the comma in a parameter expansion. So I can't
think of any solution except limiting math evaluation to the C locale.
So what can we do?
I did a grep for mon_decimal_point in /usr/share/i18n/locales to see
if any other characters are used as decimal separators. It indicates
that Portugal use `$' as their decimal separator. Seems weird. Apart
from that it is , or . for the rest of the world except Burkina Faso
who apparently use something outside the normal ASCII range.
Currently, a bug prevents locale handling for printf (on at least some
platforms). The bug causing this is in math.c where it does:
prev_locale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC, "POSIX");
The second setlocale call clobbers prev_locale - we have to use
dupstring(). The patch fixes this.
Oliver
diff -ur zsh-latest/Src/math.c localeprob2/Src/math.c
--- zsh-latest/Src/math.c 2002-12-19 10:58:19.000000000 +0000
+++ localeprob2/Src/math.c 2003-03-09 01:13:18.000000000 +0000
@@ -399,12 +399,12 @@
/* it's a float */
yyval.type = MN_FLOAT;
#ifdef USE_LOCALE
- prev_locale = setlocale(LC_NUMERIC, NULL);
+ prev_locale = dupstring(setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, "POSIX");
#endif
yyval.u.d = strtod(ptr, &nptr);
#ifdef USE_LOCALE
- setlocale(LC_NUMERIC, prev_locale);
+ if (prev_locale) setlocale(LC_NUMERIC, prev_locale);
#endif
if (ptr == nptr || *nptr == '.') {
zerr("bad floating point constant", NULL, 0);
Messages sorted by:
Reverse Date,
Date,
Thread,
Author