1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

Propagate float/integer type in arithmetic assignment.

Add test.

Mention this and also floating point mod change in README.
This commit is contained in:
Peter Stephenson 2015-01-12 16:38:00 +00:00
parent 626650f20e
commit 5f4325a0a4
4 changed files with 88 additions and 2 deletions

View file

@ -1,5 +1,8 @@
2015-01-12 Peter Stephenson <p.stephenson@samsung.com>
* 34255: README, Src/math.c, Test/C01arith.ztst: propagate type
from variable assignment. Also note 34230 in README.
* 34253: Doc/Zsh/contrib.yo: warning on integer arithmetic
for zcalc, c.f. 34194.

48
README
View file

@ -35,6 +35,54 @@ Zsh is a shell with lots of features. For a list of some of these, see the
file FEATURES, and for the latest changes see NEWS. For more
details, see the documentation.
Incompatibilites between 5.0.7 and 5.0.8
----------------------------------------
A couple of arithmetic operations have changed: the new behaviour
is intended to be more consistent, but is not compatible with the old.
Previously, the modulus operation, `%', implicitly converted the
operation to integer and output an integer result, even if one
or both of the arguments were floating point. Now, the C math
library fmod() operator is used to implement the operation where
one of the arguments is floating point. For example:
Old behavour:
% print $(( 5.5 % 2 ))
1
New behaviour:
% print $(( 5.5 % 2 ))
1.5
Previously, assignments to variables assigned the correct type to
variables declared as floating point or integer, but this type was
not propagated to the value of the expression, as a C programmer
would naturally expect. Now, the type of the variable is propagated
so long as the variable is declared as a numeric type (however this
happened, e.g. the variable may have been implicitly typed by a
previous assignment). For example:
Old behaviour:
% integer var
% print $(( var = 5.5 / 2.0 ))
2.2000000000000002
% print $var
2
(the actual rounding error may vary).
New behaviour:
% integer var
% print $(( var = 5.5 / 2.0 ))
2
% print $var
2
Incompatibilities between 5.0.2 and 5.0.5
-----------------------------------------

View file

@ -880,6 +880,8 @@ getcvar(char *s)
static mnumber
setmathvar(struct mathvalue *mvp, mnumber v)
{
Param pm;
if (mvp->pval) {
/*
* This value may have been hanging around for a while.
@ -909,7 +911,32 @@ setmathvar(struct mathvalue *mvp, mnumber v)
if (noeval)
return v;
untokenize(mvp->lval);
setnparam(mvp->lval, v);
pm = setnparam(mvp->lval, v);
if (pm) {
/*
* If we are performing an assignment, we return the
* number with the same type as the parameter we are
* assigning to, in the spirit of the way assignments
* in C work. Note this was a change to long-standing
* zsh behaviour.
*/
switch (PM_TYPE(pm->node.flags)) {
case PM_INTEGER:
if (v.type != MN_INTEGER) {
v.u.l = (zlong)v.u.d;
v.type = MN_INTEGER;
}
break;
case PM_EFLOAT:
case PM_FFLOAT:
if (v.type != MN_FLOAT) {
v.u.d = (double)v.u.l;
v.type = MN_FLOAT;
}
break;
}
}
return v;
}

View file

@ -16,7 +16,7 @@
print -- $(( rnd = there * 10000 ))
# save rounding problems by converting to integer
0:basic floating point arithmetic
>31415.
>31415
integer rnd
(( rnd = ((29.1 % 13.0 * 10) + 0.5) ))
@ -300,3 +300,11 @@
print $(( 0b2 ))
1:Binary numbers don't tend to have 2's in
?(eval):1: bad math expression: operator expected at `2 '
integer varassi
print $(( varassi = 5.5 / 2.0 ))
print $varassi
0:Integer variable assignment converts result to integer
>2
>2
# It's hard to test for integer to float.