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:
parent
626650f20e
commit
5f4325a0a4
4 changed files with 88 additions and 2 deletions
|
@ -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
48
README
|
@ -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
|
||||
-----------------------------------------
|
||||
|
||||
|
|
29
Src/math.c
29
Src/math.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue