zsh-workers
 help / color / mirror / code / Atom feed
* Math expression evaluation error?
@ 2015-01-09 19:46 jdh
  2015-01-09 20:15 ` Peter Stephenson
  0 siblings, 1 reply; 29+ messages in thread
From: jdh @ 2015-01-09 19:46 UTC (permalink / raw)
  To: zsh-workers

I believe I read that math expression evaluation will convert all
calculations in an expression if "any" value in that expression is a
real value.

That is not true if the word "any" is true or a bug has crawled into the
numeric expression evaluator.  Or I read wrong..

Example on my system, zsh 5.0.7 (i686-pc-linux-gnu), I get the following
results for the shown example:

$ echo $(( 6+3/8. + 10 + 5/8. )) $(( 6+3/8 + 10 + 5/8. ))
                               17. 16.625

In the above case only the second term which contains a real number is
evaluated as real , the previous term is taken as integer and decimal
values are truncated (non-existent.   This same behavior is demonstrated
in zcalc.  Probably uses the same logic.

Though I understand why this happens (or think I do).  It could cause
someone a major mistake if they are unaware of this and rely on the outcome.

Regards

  Darel


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 19:46 Math expression evaluation error? jdh
@ 2015-01-09 20:15 ` Peter Stephenson
  2015-01-09 21:40   ` jdh
  0 siblings, 1 reply; 29+ messages in thread
From: Peter Stephenson @ 2015-01-09 20:15 UTC (permalink / raw)
  To: jdh, zsh-workers

On Fri, 09 Jan 2015 11:46:44 -0800
jdh <dhenman@gmail.com> wrote:
> I believe I read that math expression evaluation will convert all
> calculations in an expression if "any" value in that expression is a
> real value.

This isn't the case and wherever this came from needs correcting.
Please instead read the documentation under ARITHMETIC EVALUATION in the
zshmisc manual for what actually happens and let us if know if you think
that is inadequate.  The actually phrasing is "Promotion of integer to
floating point values is performed where necessary".  It also refers
above that to C --- there's an underlying assumption here that the user
has some idea of the operation of C-like languages, which might of
course not be the case.  "Where necessary" is in general where an
operator has a floating point number as one argument and an integer as
another; a C programmer would recognise the use of the word "promotion"
as implying this, a general user probably not.  So the wording could
probably be improved.  Brief and to the point suggestions on this from
anyone are welcome (long rambles on why anyone doesn't understand it
may be invigorating for the rambler but are less useful to us as
developers :-)).

See also the following shell option:

FORCE_FLOAT
       Constants in arithmetic evaluation will be treated  as  floating
       point  even without the use of a decimal point.  Integers in any
       base will be converted.

This is most useful in zcalc, which actually has an option for this.

       If the option `-f' is set, all numbers are treated  as  floating
       point,  hence for example the expression `3/4' evaluates to 0.75
       rather than 0.  Options must appear in separate words.

pws


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 20:15 ` Peter Stephenson
@ 2015-01-09 21:40   ` jdh
  2015-01-09 22:19     ` Ray Andrews
  2015-01-09 22:40     ` Peter Stephenson
  0 siblings, 2 replies; 29+ messages in thread
From: jdh @ 2015-01-09 21:40 UTC (permalink / raw)
  To: zsh-workers

Thanks for the detailed explanation.   I suggest that the an additional 
line be added to the manual, which would say something like:

"   Caution:  The evaluation of an expression is taken a term at a time 
and if there are mixed terms , say integer only and  float terms , the 
integer only ones will not be promoted to real values and the result of 
the whole expression would be an error to common standards. One can use 
the -f option or the  FORCE_FLOAT environment variable to change this 
behavior."

I apologize if this is in the manual already.

Regards.

On 2015年01月09日 12:15, Peter Stephenson wrote:
> On Fri, 09 Jan 2015 11:46:44 -0800
> jdh <dhenman@gmail.com> wrote:
>> I believe I read that math expression evaluation will convert all
>> calculations in an expression if "any" value in that expression is a
>> real value.
> This isn't the case and wherever this came from needs correcting.
> Please instead read the documentation under ARITHMETIC EVALUATION in the
> zshmisc manual for what actually happens and let us if know if you think
> that is inadequate.  The actually phrasing is "Promotion of integer to
> floating point values is performed where necessary".  It also refers
> above that to C --- there's an underlying assumption here that the user
> has some idea of the operation of C-like languages, which might of
> course not be the case.  "Where necessary" is in general where an
> operator has a floating point number as one argument and an integer as
> another; a C programmer would recognise the use of the word "promotion"
> as implying this, a general user probably not.  So the wording could
> probably be improved.  Brief and to the point suggestions on this from
> anyone are welcome (long rambles on why anyone doesn't understand it
> may be invigorating for the rambler but are less useful to us as
> developers :-)).
>
> See also the following shell option:
>
> FORCE_FLOAT
>         Constants in arithmetic evaluation will be treated  as  floating
>         point  even without the use of a decimal point.  Integers in any
>         base will be converted.
>
> This is most useful in zcalc, which actually has an option for this.
>
>         If the option `-f' is set, all numbers are treated  as  floating
>         point,  hence for example the expression `3/4' evaluates to 0.75
>         rather than 0.  Options must appear in separate words.
>
> pws


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 21:40   ` jdh
@ 2015-01-09 22:19     ` Ray Andrews
  2015-01-09 23:06       ` Lawrence Velázquez
  2015-01-09 22:40     ` Peter Stephenson
  1 sibling, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-09 22:19 UTC (permalink / raw)
  To: zsh-workers

On 01/09/2015 01:40 PM, jdh wrote:
> Thanks for the detailed explanation.   I suggest that the an 
> additional line be added to the manual, which would say something like:
>
    {
    $ echo $(( 6+3/8. + 10 + 5/8  ))
    $ echo $(( 6+3/8  + 10 + 5/8. ))
    $ echo $(( 6+3/8. + 10 + 5/8. ))
    $ echo $(( 6+3/8  + 10 + 5/8  ))
    }

    16.375
    16.625
    17.
    16           << really?

    $ setopt force_float

    {
    $ echo $(( 6+3/8. + 10 + 5/8  ))
    $ echo $(( 6+3/8  + 10 + 5/8. ))
    $ echo $(( 6+3/8. + 10 + 5/8. ))
    $ echo $(( 6+3/8  + 10 + 5/8  ))
    }

    17.
    17.
    17.
    17.


Thanks for the heads up, I now know not to trust zsh math without the 
option.
I wonder tho why anyone would ever want the first set of results. 
Who/why/when
do we want bad math? Wouldn't we prefer accurate results as the default with
the option to have broken math for people who like broken math? Why not have
it work properly and that's that--nothing to explain, it just works as 
you'd expect it to work?

  6 + 3/8 + 10 + 5/8 ...
what sane calculator is going to give me '16' for that?


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 21:40   ` jdh
  2015-01-09 22:19     ` Ray Andrews
@ 2015-01-09 22:40     ` Peter Stephenson
  2015-01-12 10:55       ` Peter Stephenson
  2015-01-14 15:02       ` Vincent Lefevre
  1 sibling, 2 replies; 29+ messages in thread
From: Peter Stephenson @ 2015-01-09 22:40 UTC (permalink / raw)
  To: jdh, zsh-workers

On Fri, 09 Jan 2015 13:40:42 -0800
jdh <dhenman@gmail.com> wrote:
> Thanks for the detailed explanation.   I suggest that the an additional 
> line be added to the manual, which would say something like:
> 
> "   Caution:  The evaluation of an expression is taken a term at a time 
> and if there are mixed terms , say integer only and  float terms , the 
> integer only ones will not be promoted to real values and the result of 
> the whole expression would be an error to common standards. One can use 
> the -f option or the  FORCE_FLOAT environment variable to change this 
> behavior."

Thanks, that's just the sort of useful feedback on what people find
confusing that we need.  I've adapted it into the appropriate section of
the manual with minor corrections.

diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index a620b73..5c334ce 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -233,6 +233,15 @@ necessary.  In addition, if any operator which requires an integer
 equivalents with assignment) is given a floating point argument, it will be
 silently rounded down to the next integer.
 
+Users should beware that, in common with many other programming
+languages but not software designed for calculation, the evaluation of
+an expression in zsh is taken a term at a time and promotion of integers
+to floating point does not occur in terms only containing integers.  A
+typical result of this is that a division such as tt(6/8) is truncated,
+in this being rounded down to 0.  The tt(FORCE_FLOAT) shell option can
+be used in scripts or functions where floating point evaluation is
+required throughout.
+
 Scalar variables can hold integer or floating point values at different
 times; there is no memory of the numeric type in this case.
 
 
pws


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 22:19     ` Ray Andrews
@ 2015-01-09 23:06       ` Lawrence Velázquez
  2015-01-09 23:52         ` Ray Andrews
  0 siblings, 1 reply; 29+ messages in thread
From: Lawrence Velázquez @ 2015-01-09 23:06 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-workers

On Jan 9, 2015, at 5:19 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:

> I wonder tho why anyone would ever want the first set of results. Who/why/when
> do we want bad math?

Mathematics restricted to the set of integers is not "bad math", no matter how much you assert that it is.

> Wouldn't we prefer accurate results as the default with the option to have broken math for people who like broken math?

Stop calling it "broken". It's the way C does math.

    % clang -Wno-format -o c-integer-div -x c - <<EOF
    heredoc> #include <stdio.h>
    heredoc> int main(void) {
    heredoc>    printf("integer division is not 'bad math': 3 / 8 = %f\n", 3 / 8);
    heredoc>    return 0;
    heredoc> }
    heredoc> EOF
    % ./c-integer-div
    integer division is not 'bad math': 3 / 8 = 0.000000

At this point, this is what a lot of programmers expect, especially since the rest of zsh's arithmetic is quite C-like.

> Why not have it work properly and that's that--nothing to explain, it just works as you'd expect it to work?

It'd work as YOU expect it to work. Plenty of other people expect it to work like C, and we'd have to explain to them why it doesn't. (We already have to do so for operator precedence and hexadecimal literals, among other things.)

> 6 + 3/8 + 10 + 5/8 ...
> what sane calculator is going to give me '16' for that?

zsh is not a calculator.

vq

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 23:06       ` Lawrence Velázquez
@ 2015-01-09 23:52         ` Ray Andrews
  2015-01-10  0:25           ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-09 23:52 UTC (permalink / raw)
  To: Lawrence Velázquez; +Cc: zsh-workers

On 01/09/2015 03:06 PM, Lawrence Velázquez wrote:
> On Jan 9, 2015, at 5:19 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
>
>> I wonder tho why anyone would ever want the first set of results. Who/why/when
>> do we want bad math?
> Mathematics restricted to the set of integers is not "bad math", no matter how much you assert that it is.

I assert nothing, I ask a question.  I just 'automatically' presume that 
zsh calculations will be done  like any normal calculator would  do them.

$ echo $(( 3/8 + 5/8 ))
0

.. if that's what people want, then that's what they'll get, it just seems
a bit strange to me.  I'd say that the very fact that I enter a fraction 
tells
the shell that I'm expecting a real number answer.  Or maybe not.

But that's just my take on it, I'm not saying.  It seems to me that if the
shell accepts the fractions then it should return the correct answer.  I'd
make integer math  the option and have accurate results as the default
but that's just me.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 23:52         ` Ray Andrews
@ 2015-01-10  0:25           ` Bart Schaefer
  2015-01-10  7:27             ` Ray Andrews
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2015-01-10  0:25 UTC (permalink / raw)
  To: Zsh hackers list

On Fri, Jan 9, 2015 at 3:52 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> It seems to me that if the
> shell accepts the fractions then it should return the correct answer.  I'd
> make integer math  the option and have accurate results as the default
> but that's just me.


3/8 is not a fraction.  Yes, in a text paragraph like this one I might
write 3/8 as a fraction because I can't write a superscript three over
a subscript eight, but in an arithmetic expression 0.375 is a fraction
and 3/8 is "integer 3 divided by integer 8", and the definition of
"divided by" includes "if both numerator and denominator are integers,
then the result must also be an integer".  As has been mentioned, this
is the way a LOT of programming languages work.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10  0:25           ` Bart Schaefer
@ 2015-01-10  7:27             ` Ray Andrews
  2015-01-10 16:53               ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-10  7:27 UTC (permalink / raw)
  To: zsh-workers

On 01/09/2015 04:25 PM, Bart Schaefer wrote:
> On Fri, Jan 9, 2015 at 3:52 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
>> It seems to me that if the
>> shell accepts the fractions then it should return the correct answer.  I'd
>> make integer math  the option and have accurate results as the default
>> but that's just me.
>
> 3/8 is not a fraction.  Yes, in a text paragraph like this one I might
> write 3/8 as a fraction because I can't write a superscript three over
> a subscript eight, but in an arithmetic expression 0.375 is a fraction
> and 3/8 is "integer 3 divided by integer 8", and the definition of
> "divided by" includes "if both numerator and denominator are integers,
> then the result must also be an integer".  As has been mentioned, this
> is the way a LOT of programming languages work.
Well, this is one of those things that won't change, but I must say that 
in my experience an overwhelming majority of people would say that 3/8 
is a fraction, and they would be surprised that in zsh, by default :

1/2 + 1/2 = 0

And I'll bet they'd wonder why even though zsh is quite capable of doing 
floating point math, it chooses to behave like an abacus by default, 
other programing languages notwithstanding.  Never mind, I'll just 
'setopt force_float' and have accuracy.   I'm glad I was forewarned 
about this, however.
>


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10  7:27             ` Ray Andrews
@ 2015-01-10 16:53               ` Bart Schaefer
  2015-01-10 18:48                 ` Ray Andrews
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2015-01-10 16:53 UTC (permalink / raw)
  To: zsh-workers

On Jan 9, 11:27pm, Ray Andrews wrote:
} Subject: Re: Math expression evaluation error?
}
} > 3/8 is not a fraction.
}
} Well, this is one of those things that won't change, but I must say that 
} in my experience an overwhelming majority of people would say that 3/8 
} is a fraction, and they would be surprised

OK, let's leave zsh out of this and try the standard "expr" utility,
which built-in arithmetic was designed to replace:

% expr 3 / 8
0
% expr 3.0 / 8.0
expr: non-numeric argument


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10 16:53               ` Bart Schaefer
@ 2015-01-10 18:48                 ` Ray Andrews
  2015-01-10 19:14                   ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-10 18:48 UTC (permalink / raw)
  To: zsh-workers

On 01/10/2015 08:53 AM, Bart Schaefer wrote:
> OK, let's leave zsh out of this and try the standard "expr" utility,
> which built-in arithmetic was designed to replace:
>
> % expr 3 / 8
> 0
> % expr 3.0 / 8.0
> expr: non-numeric argument
>
>
Bart, I shouldn't argue because it's to the point of irritation, and 
that is never positive, but:  My stance is not to think about 'expr' or 
other programming languages, or what ksh did in '79 or about glorious 
traditions going back to the mainframe days, or any of that.  My stance 
is just to ask: What is most useful?  What would produce the maximum 
utility along with the least surprise, especially for a new user? In 
which direction is 'the future'?

I now know to just set the option, and I'm all good, problem averted. So 
it really is just about philosophy.  IMHO we have moved past the abacus 
and a new user, once s/he learns  that zsh does internal 
arithmetic--that it has an excellent internal calculator--will expect 
that: 3/8 + 5/8 = 1.  I think that 99% of humanity would expect that.  
I'm a math tutor, and I am positive that every one of  my students would 
expect it.  I'm not saying that integer arithmetic should not be 
available, but should it be the default?  How often does anyone want or 
expect:  1/2 + 1/2 = 0? Maybe someone really needs that, and far be it 
from me to deprive them of it, but I'm claiming that it doesn't happen 
very often.

    {
       echo $(( 1/2 + 1/2 ));
       echo $(( .5 + .5 ));
    }
    0
    1

... is, in my mind, a monstrosity.  The very act of typing: " 1/2 " is a 
request for floating point arithmetic in just about exactly the same way 
that typing a decimal point is.  I'm not sure that " 1/2 " means 
anything at all within the confines of integer/abacus arithmetic, I 
think it's an imaginary number and should return an error, not zero.  
IMHO the zsh manual for arithmetic would read something like this:

"
Zsh has a powerful built in calculator. Type expressions just as you 
would in any other calculator and get the results you expect with no 
strange surprises or gotchas. For example:

     $ echo $(( ((.5 + 1/2) * 2) **2
     4

Zsh also does integer arithmetic.  Users of the abacus will appreciate 
this ;-) To enter integer mode:

    $ setopt integer_arithmetic

In this mode, the above expression returns '1'. Have fun with that, 
however we   recommend you not use this mode for teaching arithmetic to 
children.
"

Just my personal opinion.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10 18:48                 ` Ray Andrews
@ 2015-01-10 19:14                   ` Bart Schaefer
  2015-01-10 22:21                     ` Ray Andrews
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2015-01-10 19:14 UTC (permalink / raw)
  To: zsh-workers

On Jan 10, 10:48am, Ray Andrews wrote:
}
} is just to ask: What is most useful?  What would produce the maximum 
} utility along with the least surprise, especially for a new user? In 
} which direction is 'the future'?

Call me a cynic or a curmudgeon as you prefer, but the future of new
users who would give so little thought and study to the tools they
are using as to find this a problem more than once, is to not use
shells at all.

It *is* probably less than ideal that "zcalc -f" is not the default
for the actual calculator utility; but pretending that $(( ... )) could
ever be described "a calculator with no surprises or gotchas" regardless
of integer arithmetic, is misleading because it isn't a calculator and
trying to think of it that way is going to cause surprises and gotchas.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10 19:14                   ` Bart Schaefer
@ 2015-01-10 22:21                     ` Ray Andrews
  2015-01-11  1:51                       ` Bart Schaefer
  0 siblings, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-10 22:21 UTC (permalink / raw)
  To: zsh-workers

On 01/10/2015 11:14 AM, Bart Schaefer wrote:
> On Jan 10, 10:48am, Ray Andrews wrote:
> }
> } is just to ask: What is most useful?  What would produce the maximum
> } utility along with the least surprise, especially for a new user? In
> } which direction is 'the future'?
>
> Call me a cynic or a curmudgeon as you prefer, but the future of new
> users who would give so little thought and study to the tools they
> are using as to find this a problem more than once, is to not use
> shells at all.

That's quite legitimate.  The 'fix' is after all very simple.  You know, in
this sort of discussion pressures can build beyond what the issue
merits.  'setopt force_float' and there's nothing more to worry about.
But so long as you wish to discuss it, I'll just do what I do and advocate
for a friendlier and more intuitive shell where possible:  However simple
the fix may be, it remains my view that the intuitive behavior should
be the default.  It's just my paradigm.  I quite understand that it will
not prevail. Not worth the price of a beer, and certainly not worth any
disturbance.
>
> It *is* probably less than ideal that "zcalc -f" is not the default

And that's all I'm saying, (but, for "$ (( ))" too).

BTW, just Googling, I see that this issue has come up time and again.
Our original poster on this thread is not the first person to be got by
this gotcha.  Why not make the issue go away, once and for all?

One could have fun with some facetious advertising:
"Try zsh, the shell where 1/2 + 1/2 = 1 !!!"

> for the actual calculator utility; but pretending that $(( ... )) could
> ever be described "a calculator with no surprises or gotchas" regardless
> of integer arithmetic, is misleading because it isn't a calculator and
> trying to think of it that way is going to cause surprises and gotchas.

Well, it could come to a question of terminology or even of hard facts.  I
myself have (until this issue came up) never done anything beyond simple
integer addition and subtraction. From what I read, $ (( )) does quite
sophisticated calculations and it is ergo, ipso facto a calculator. And 
I also
presume that it accesses all the power of 'zcalc' (because why 
*wouldn't* it?)

However, if it does have gotchas in it (I mean beyond the current subject)
I can't say, I just presume it does what it advertises itself to do, and
my experiments with it bare that out-- and that's 'calculation' as I use
the word. But don't  take my pseudo manual as anything more than a
comment please it's just what I wish was the case.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-10 22:21                     ` Ray Andrews
@ 2015-01-11  1:51                       ` Bart Schaefer
  2015-01-11  5:10                         ` Ray Andrews
  0 siblings, 1 reply; 29+ messages in thread
From: Bart Schaefer @ 2015-01-11  1:51 UTC (permalink / raw)
  To: zsh-workers

On Jan 10,  2:21pm, Ray Andrews wrote:
}
} BTW, just Googling, I see that this issue has come up time and again.
} Our original poster on this thread is not the first person to be got by
} this gotcha.  Why not make the issue go away, once and for all?

Because there is such a thing as standardized behavior across shells,
and while it is fine to add or extend features, egregiously changing
the behavior of the common subset is generally a bad idea.

} I also presume that it accesses all the power of 'zcalc' (because why 
} *wouldn't* it?)

It's actually the other way around.  zcalc accesses the power of $(( ))
but "looks" a bit more like a calculator.

-- 
Barton E. Schaefer


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-11  1:51                       ` Bart Schaefer
@ 2015-01-11  5:10                         ` Ray Andrews
  2015-01-12  9:17                           ` Vincent Lefevre
  0 siblings, 1 reply; 29+ messages in thread
From: Ray Andrews @ 2015-01-11  5:10 UTC (permalink / raw)
  To: zsh-workers

On 01/10/2015 05:51 PM, Bart Schaefer wrote:
> Because there is such a thing as standardized behavior across shells,
> and while it is fine to add or extend features, egregiously changing
> the behavior of the common subset is generally a bad idea.

Sure.  That's the best argument for leaving it alone and of course it is
perfectly sound.  I'd go the other way, liking friendliness more, but
I respect your decision. And I could be quite wrong about 1/2 + 1/2 = 0,
strange as it looks to me, rounding down could be vital to some code
somewhere.


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-11  5:10                         ` Ray Andrews
@ 2015-01-12  9:17                           ` Vincent Lefevre
  2015-01-12 16:18                             ` ZyX
  0 siblings, 1 reply; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-12  9:17 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-10 21:10:16 -0800, Ray Andrews wrote:
> Sure.  That's the best argument for leaving it alone and of course it is
> perfectly sound.  I'd go the other way, liking friendliness more, but
> I respect your decision. And I could be quite wrong about 1/2 + 1/2 = 0,
> strange as it looks to me, rounding down could be vital to some code
> somewhere.

It's only a notation problem. Unfortunately / was chosen (historically,
not by zsh) as the symbol for integer division. The shell expression
1/2 + 1/2 just means:

  integer_div(1,2) + integer_div(1,2)

where integer_div is the integer division function, which gives 0.
This is perfectly correct math.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 22:40     ` Peter Stephenson
@ 2015-01-12 10:55       ` Peter Stephenson
  2015-01-14 15:02       ` Vincent Lefevre
  1 sibling, 0 replies; 29+ messages in thread
From: Peter Stephenson @ 2015-01-12 10:55 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

On Fri, 9 Jan 2015 22:40:34 +0000
Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> +Users should beware that, in common with many other programming
> +languages but not software designed for calculation, the evaluation of
> +an expression in zsh is taken a term at a time and promotion of integers
> +to floating point does not occur in terms only containing integers.  A
> +typical result of this is that a division such as tt(6/8) is truncated,
> +in this being rounded down to 0.  The tt(FORCE_FLOAT) shell option can
> +be used in scripts or functions where floating point evaluation is
> +required throughout.

Before this drifts out of my mind, here's a similar warning for zcalc.

Assuming anybody actually bothers to read the documentation...

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 5043243..00ede52 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -3227,8 +3227,18 @@ A reasonably powerful calculator based on zsh's arithmetic evaluation
 facility.  The syntax is similar to that of formulae in most programming
 languages; see
 ifzman(the section `Arithmetic Evaluation' in zmanref(zshmisc))\
-ifnzman(noderef(Arithmetic Evaluation)) for details.  The mathematical
-library tt(zsh/mathfunc) will be loaded if it is available; see
+ifnzman(noderef(Arithmetic Evaluation)) for details.
+
+Non-programmers should note that, as in many other programming
+languages, expressions involving only integers (whether constants
+without a `tt(.)', variables containing such constants as strings, or
+variables declared to be integers) are by default evaluated using
+integer arithmetic, which is not how an ordinary desk calculator
+operates.  To force floating point operation, pass the option tt(-f);
+see further notes below.
+
+The mathematical library tt(zsh/mathfunc) will be loaded if it is
+available; see
 ifzman(the section `The zsh/mathfunc Module' in zmanref(zshmodules))\
 ifnzman(noderef(The zsh/mathfunc Module)).  The mathematical functions
 correspond to the raw system libraries, so trigonometric functions are

pws


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-12  9:17                           ` Vincent Lefevre
@ 2015-01-12 16:18                             ` ZyX
  2015-01-13 16:00                               ` Vincent Lefevre
  0 siblings, 1 reply; 29+ messages in thread
From: ZyX @ 2015-01-12 16:18 UTC (permalink / raw)
  To: Vincent Lefevre, zsh-workers

12.01.2015, 12:18, "Vincent Lefevre" <vincent@vinc17.net>:
> On 2015-01-10 21:10:16 -0800, Ray Andrews wrote:
>>  Sure.  That's the best argument for leaving it alone and of course it is
>>  perfectly sound.  I'd go the other way, liking friendliness more, but
>>  I respect your decision. And I could be quite wrong about 1/2 + 1/2 = 0,
>>  strange as it looks to me, rounding down could be vital to some code
>>  somewhere.
>
> It's only a notation problem. Unfortunately / was chosen (historically,
> not by zsh) as the symbol for integer division. The shell expression
> 1/2 + 1/2 just means:
>
>   integer_div(1,2) + integer_div(1,2)
>
> where integer_div is the integer division function, which gives 0.
> This is perfectly correct math.

It is not integer division. 1.0/2 and 1/2.0 will give the same result: 0.5. If you want to see language with operator for integer division check out Python-3: it has / for always-floating-point-unless-overridden and // for always-integral-unless-overridden (note: *not* integer (i.e. int type), having float on either side of // will result in floating-point integral value). Though as usual you can do anything you like in your own class, including `rm -rf ~` when trying to use division.

I would rather call it “type-specific division”. And I think that Python-3 way is least surprising and most convenient variant. Though you should not use // for dividing non-integral floats: 1.5//0.1 == 14.0 (rounding+decimal-binary conversion issues I guess).

>
> --
> Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
> Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-12 16:18                             ` ZyX
@ 2015-01-13 16:00                               ` Vincent Lefevre
  2015-01-13 23:03                                 ` ZyX
  0 siblings, 1 reply; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-13 16:00 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-12 19:18:22 +0300, ZyX wrote:
> 12.01.2015, 12:18, "Vincent Lefevre" <vincent@vinc17.net>:
> > It's only a notation problem. Unfortunately / was chosen (historically,
> > not by zsh) as the symbol for integer division. The shell expression
> > 1/2 + 1/2 just means:
> >
> >   integer_div(1,2) + integer_div(1,2)
> >
> > where integer_div is the integer division function, which gives 0.
> > This is perfectly correct math.
> 
> It is not integer division.

In POSIX, it is always an integer division.

> 1.0/2 and 1/2.0 will give the same result: 0.5.

because 1.0 and 2.0 don't have an integer type. Therefore the result is
unspecified by POSIX, and zsh chooses to do a floating-point division.

> If you want to see language with operator for integer division check
> out Python-3: it has / for always-floating-point-unless-overridden
> and // for always-integral-unless-overridden

For Python, but not for zsh, unfortunately. But this choice comes
from POSIX historical behavior (and perhaps earlier).

> I would rather call it “type-specific division”.

In zsh. In POSIX, it is *always* an integer division. There is no
floating-point there.

An alternative choice zsh could have done is to return an error
if the / operator is used in a floating-point context, and use a
different operator for the floating-point division. However the
use of / for integer division could still be surprising.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-13 16:00                               ` Vincent Lefevre
@ 2015-01-13 23:03                                 ` ZyX
  2015-01-14 14:47                                   ` Vincent Lefevre
  0 siblings, 1 reply; 29+ messages in thread
From: ZyX @ 2015-01-13 23:03 UTC (permalink / raw)
  To: Vincent Lefevre, zsh-workers

13.01.2015, 19:01, "Vincent Lefevre" <vincent@vinc17.net>:
> On 2015-01-12 19:18:22 +0300, ZyX wrote:
>>  12.01.2015, 12:18, "Vincent Lefevre" <vincent@vinc17.net>:
>>>  It's only a notation problem. Unfortunately / was chosen (historically,
>>>  not by zsh) as the symbol for integer division. The shell expression
>>>  1/2 + 1/2 just means:
>>>
>>>    integer_div(1,2) + integer_div(1,2)
>>>
>>>  where integer_div is the integer division function, which gives 0.
>>>  This is perfectly correct math.
>>  It is not integer division.
>
> In POSIX, it is always an integer division.

What?!

1. How POSIX is related? Zsh is not a POSIX shell and it is not emulation mode that is being discussed here.
2. If this standard is correct: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tagtcjh_15 then it references ISO C standard. The ISO C standard (C99) says the following for multiplicative operators:

   > 6.5.5 Multiplicative operators
   …
   > 3 The usual arithmetic conversions are performed on the operands.
   > 2 Each of the operands shall have arithmetic type. The operands of the % operator shall
   >   have integer type.
   …
   > 5 The result of the / operator is the quotient from the division of the first operand by the
   >   second; the result of the % operator is the remainder. In both operations, if the value of
   >   the second operand is zero, the behavior is undefined.
   > 6 When integers are divided …

   Where do you see a requirement for `/` to be integer division?
3. POSIX (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04) says that “Only signed long integer arithmetic is required.” And the section referenced there talks about signed long or double. Signed long integer arithmetic is *required* to be in there, but signed long integer arithmetics is *not required* to be the *only* arithmetics present in POSIX shell.

So no, `/` has nothing to do with integer division, except that the referenced C standard expects well-defined integer division in case two integers are divided. If you have another POSIX standard or another interpretation please show it here.

>>  1.0/2 and 1/2.0 will give the same result: 0.5.
>
> because 1.0 and 2.0 don't have an integer type. Therefore the result is
> unspecified by POSIX, and zsh chooses to do a floating-point division.
>>  If you want to see language with operator for integer division check
>>  out Python-3: it has / for always-floating-point-unless-overridden
>>  and // for always-integral-unless-overridden
>
> For Python, but not for zsh, unfortunately. But this choice comes
> from POSIX historical behavior (and perhaps earlier).
>>  I would rather call it “type-specific division”.
>
> In zsh. In POSIX, it is *always* an integer division. There is no
> floating-point there.
>
> An alternative choice zsh could have done is to return an error
> if the / operator is used in a floating-point context, and use a
> different operator for the floating-point division. However the
> use of / for integer division could still be surprising.
>
> --
> Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
> Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-13 23:03                                 ` ZyX
@ 2015-01-14 14:47                                   ` Vincent Lefevre
  2015-01-14 21:37                                     ` ZyX
  0 siblings, 1 reply; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-14 14:47 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-14 02:03:33 +0300, ZyX wrote:
> 13.01.2015, 19:01, "Vincent Lefevre" <vincent@vinc17.net>:
> > In POSIX, it is always an integer division.
> 
> What?!
> 
> 1. How POSIX is related? Zsh is not a POSIX shell and it is not emulation mode that is being discussed here.

Zsh is partly based on POSIX for compatibility. The big difference
is the lack of word splitting (unless SH_WORD_SPLIT is set). Otherwise
I think that one should expect similar behavior, unless there is a
good reason.

> 2. If this standard is correct: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tagtcjh_15 then it references ISO C standard.
[...]
>    Where do you see a requirement for `/` to be integer division?

The context is an integer arithmetic. Thus / is necessarily an
integer division, like in C with integer types.

> 3. POSIX (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04) says that “Only signed long integer arithmetic is required.” And the section referenced there talks about signed long or double. Signed long integer arithmetic is *required* to be in there, but signed long integer arithmetics is *not required* to be the *only* arithmetics present in POSIX shell.

It says: "as long as it does not affect the results in cases where
there is no overflow"

If $((1/2)) gave 0.5 in some shells, I fear this would break various
scripts.

So, if a real-floating type is used, then for "/", I suppose that
the implementation should do a floor() after the division if the
context has operands recognized as integers, which is here equivalent
to the integer division despite the two roundings (proved in
http://www.vinc17.net/research/papers/rr_intdiv).

But POSIX doesn't specify the arithmetic evaluation on expressions
other than signed long integer arithmetic. An implementation that
decides that $((1.0/2)) gives 17 "as an extension" could still be
conforming.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-09 22:40     ` Peter Stephenson
  2015-01-12 10:55       ` Peter Stephenson
@ 2015-01-14 15:02       ` Vincent Lefevre
  2015-01-14 15:38         ` Peter Stephenson
  1 sibling, 1 reply; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-14 15:02 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-09 22:40:34 +0000, Peter Stephenson wrote:
> diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
> index a620b73..5c334ce 100644
> --- a/Doc/Zsh/arith.yo
> +++ b/Doc/Zsh/arith.yo
> @@ -233,6 +233,15 @@ necessary.  In addition, if any operator which requires an integer
>  equivalents with assignment) is given a floating point argument, it will be
>  silently rounded down to the next integer.
>  
> +Users should beware that, in common with many other programming
> +languages but not software designed for calculation, the evaluation of
> +an expression in zsh is taken a term at a time and promotion of integers
> +to floating point does not occur in terms only containing integers.  A
> +typical result of this is that a division such as tt(6/8) is truncated,
> +in this being rounded down to 0.  The tt(FORCE_FLOAT) shell option can
> +be used in scripts or functions where floating point evaluation is
> +required throughout.

This explanation is incorrect (or very ambiguous). FORCE_FLOAT doesn't
force a floating-point evaluation; it just converts *constants* to
floating-point. See the differences:

ypig% setopt FORCE_FLOAT
ypig% integer a=1 b=2
ypig% echo $((1/2))
0.5
ypig% echo $((a/b))
0

I'm wondering whether this is the expected behavior, though.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-14 15:02       ` Vincent Lefevre
@ 2015-01-14 15:38         ` Peter Stephenson
  2015-01-15 14:58           ` Peter Stephenson
  0 siblings, 1 reply; 29+ messages in thread
From: Peter Stephenson @ 2015-01-14 15:38 UTC (permalink / raw)
  To: zsh-workers

On Wed, 14 Jan 2015 16:02:58 +0100
Vincent Lefevre <vincent@vinc17.net> wrote:
> FORCE_FLOAT doesn't
> force a floating-point evaluation; it just converts *constants* to
> floating-point. See the differences:
> 
> ypig% setopt FORCE_FLOAT
> ypig% integer a=1 b=2
> ypig% echo $((1/2))
> 0.5
> ypig% echo $((a/b))
> 0
> 
> I'm wondering whether this is the expected behavior, though.

I wouldn't have thought so --- I would guess when forcing floating
point calculations people would expect this to happen everywhere,
despite what the documentation for the option says.

This shouldn't be problematic if it's already working for constants
since variables appear in just the same contexts.

diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 076aaf4..8a0222c 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -496,9 +496,10 @@ pindex(NOFORCEFLOAT)
 cindex(floating point, forcing use of)
 cindex(forcing use of floating point)
 item(tt(FORCE_FLOAT))(
-Constants in arithmetic evaluation will be treated as floating point
-even without the use of a decimal point.  Integers in any base
-will be converted.
+Constants in arithmetic evaluation will be treated as
+floating point even without the use of a decimal point; the
+values of integer variables will be converted to floating point when
+used in arithmetic expressions.  Integers in any base will be converted.
 )
 pindex(GLOB)
 pindex(NO_GLOB)
diff --git a/Src/math.c b/Src/math.c
index db42d0f..c047725 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -336,16 +336,27 @@ enum prec_type {
 static mnumber
 getmathparam(struct mathvalue *mptr)
 {
+    mnumber result;
     if (!mptr->pval) {
 	char *s = mptr->lval;
 	mptr->pval = (Value)zhalloc(sizeof(struct value));
 	if (!getvalue(mptr->pval, &s, 1))
 	{
 	    mptr->pval = NULL;
+	    if (isset(FORCEFLOAT)) {
+		result.type = MN_FLOAT;
+		result.u.d = 0.0;
+		return result;
+	    }
 	    return zero_mnumber;
 	}
     }
-    return getnumvalue(mptr->pval);
+    result = getnumvalue(mptr->pval);
+    if (isset(FORCEFLOAT) && result.type == MN_INTEGER) {
+	result.type = MN_FLOAT;
+	result.u.d = (double)result.u.l;
+    }
+    return result;
 }
 
 static mnumber
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index 8e0730d..ea87af2 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -308,3 +308,13 @@
 >2
 >2
 # It's hard to test for integer to float.
+
+  integer ff1=3 ff2=4
+  print $(( ff1/ff2 ))
+  setopt force_float
+  print $(( ff1/ff2 ))
+  unsetopt force_float
+0:Variables are forced to floating point where necessary
+# 0.75 is exactly representable, don't expect rounding error.
+>0
+>0.75


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-14 14:47                                   ` Vincent Lefevre
@ 2015-01-14 21:37                                     ` ZyX
  2015-01-15 13:34                                       ` Vincent Lefevre
  0 siblings, 1 reply; 29+ messages in thread
From: ZyX @ 2015-01-14 21:37 UTC (permalink / raw)
  To: Vincent Lefevre, zsh-workers

14.01.2015, 17:48, "Vincent Lefevre" <vincent@vinc17.net>:
> On 2015-01-14 02:03:33 +0300, ZyX wrote:
>>  13.01.2015, 19:01, "Vincent Lefevre" <vincent@vinc17.net>:
>>>  In POSIX, it is always an integer division.
>>  What?!
>>
>>  1. How POSIX is related? Zsh is not a POSIX shell and it is not emulation mode that is being discussed here.
>
> Zsh is partly based on POSIX for compatibility. The big difference
> is the lack of word splitting (unless SH_WORD_SPLIT is set). Otherwise
> I think that one should expect similar behavior, unless there is a
> good reason.
>>  2. If this standard is correct: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tagtcjh_15 then it references ISO C standard.
>
> [...]
>>     Where do you see a requirement for `/` to be integer division?
>
> The context is an integer arithmetic. Thus / is necessarily an
> integer division, like in C with integer types.

No. The context explicitly says that signed long integers or doubles should be used. Context of the ISO C standard obviously does not say anything like this.

>>  3. POSIX (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04) says that “Only signed long integer arithmetic is required.” And the section referenced there talks about signed long or double. Signed long integer arithmetic is *required* to be in there, but signed long integer arithmetics is *not required* to be the *only* arithmetics present in POSIX shell.
>
> It says: "as long as it does not affect the results in cases where
> there is no overflow"
>
> If $((1/2)) gave 0.5 in some shells, I fear this would break various
> scripts.

This is as well against the standard because in C division of two integers yields integers and is performed according to integer division rules.

>
> So, if a real-floating type is used, then for "/", I suppose that
> the implementation should do a floor() after the division if the
> context has operands recognized as integers, which is here equivalent
> to the integer division despite the two roundings (proved in
> http://www.vinc17.net/research/papers/rr_intdiv).
>
> But POSIX doesn't specify the arithmetic evaluation on expressions
> other than signed long integer arithmetic. An implementation that
> decides that $((1.0/2)) gives 17 "as an extension" could still be
> conforming.

Nope, it cannot ever be conforming. POSIX does this by saying that semantic of operation is the same as in C, except that only signed long integers and doubles are allowed. In C 1.0/2 gives 0.5 because this is how conversion rules are defined.

If you want to say it does *show me where POSIX explicitly forbids doubles in definition of arithmetic expansion*. I only see it explicitly forbidding the internal shell type (which is allowed to be greater then long or even be floating-point) to affect the results of operation (unless there is an overflow which is in any case not defined for signed integers) which is the case if one tries to divide two integers (effectively requiring shell to keep track on types even if it wants to use double for everything) and also in case doubles are used, effectively meaning that if shell supports doubles it should yield doubles after division involving a double: “The evaluation of arithmetic expressions shall be equivalent to that described in Section 6.5, Expressions, of the ISO C standard.”.

>
> --
> Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
> Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-14 21:37                                     ` ZyX
@ 2015-01-15 13:34                                       ` Vincent Lefevre
  2015-01-15 13:41                                         ` Vincent Lefevre
  2015-01-15 18:32                                         ` ZyX
  0 siblings, 2 replies; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-15 13:34 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-15 00:37:43 +0300, ZyX wrote:
> 14.01.2015, 17:48, "Vincent Lefevre" <vincent@vinc17.net>:
> > On 2015-01-14 02:03:33 +0300, ZyX wrote:
> >>  13.01.2015, 19:01, "Vincent Lefevre" <vincent@vinc17.net>:
> >>>  In POSIX, it is always an integer division.
> >>  What?!
> >>
> >>  1. How POSIX is related? Zsh is not a POSIX shell and it is not emulation mode that is being discussed here.
> >
> > Zsh is partly based on POSIX for compatibility. The big difference
> > is the lack of word splitting (unless SH_WORD_SPLIT is set). Otherwise
> > I think that one should expect similar behavior, unless there is a
> > good reason.
> >>  2. If this standard is correct: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tagtcjh_15 then it references ISO C standard.
> >
> > [...]
> >>     Where do you see a requirement for `/` to be integer division?
> >
> > The context is an integer arithmetic. Thus / is necessarily an
> > integer division, like in C with integer types.
> 
> No. The context explicitly says that signed long integers or doubles
> should be used. Context of the ISO C standard obviously does not say
> anything like this.

Wrong. The context of $((...)) is signed long arithmetic. If a shell
wants to use double's (such as 1.0), that's only an extension.

> > But POSIX doesn't specify the arithmetic evaluation on expressions
> > other than signed long integer arithmetic. An implementation that
> > decides that $((1.0/2)) gives 17 "as an extension" could still be
> > conforming.
> 
> Nope, it cannot ever be conforming. POSIX does this by saying that
> semantic of operation is the same as in C,

Only for what it specifies.

> except that only signed long integers and doubles are allowed.

No, POSIX says "As an extension, the shell may recognize arithmetic
expressions beyond those listed." and does not specify anything on
such expressions. $((1.0/2)) is such an arithmetic expression beyond
those listed.

In particular, it does *not* say that "only signed long integers and
doubles are allowed". A shell could implement other types (number
fields or whatever), and specific operators. And note that in such
an expression, "/" is not necessarily an operator, but could be part
of a constant.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-15 13:34                                       ` Vincent Lefevre
@ 2015-01-15 13:41                                         ` Vincent Lefevre
  2015-01-15 18:32                                         ` ZyX
  1 sibling, 0 replies; 29+ messages in thread
From: Vincent Lefevre @ 2015-01-15 13:41 UTC (permalink / raw)
  To: zsh-workers

On 2015-01-15 14:34:21 +0100, Vincent Lefevre wrote:
> > > But POSIX doesn't specify the arithmetic evaluation on expressions
> > > other than signed long integer arithmetic. An implementation that
> > > decides that $((1.0/2)) gives 17 "as an extension" could still be
> > > conforming.
> > 
> > Nope, it cannot ever be conforming. POSIX does this by saying that
> > semantic of operation is the same as in C,
> 
> Only for what it specifies.

BTW, note also that the ISO C standard doesn't specify the accuracy,
unless Annex F (IEEE 754) is supported (which is not required by
POSIX). So, even if the shell claims to implement floating-point
arithmetic, any floating-point number as the result of $((1.0/2))
would be conforming.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-14 15:38         ` Peter Stephenson
@ 2015-01-15 14:58           ` Peter Stephenson
  0 siblings, 0 replies; 29+ messages in thread
From: Peter Stephenson @ 2015-01-15 14:58 UTC (permalink / raw)
  To: zsh-workers

On Wed, 14 Jan 2015 15:38:42 +0000
Peter Stephenson <p.stephenson@samsung.com> wrote:
> I wouldn't have thought so --- I would guess when forcing floating
> point calculations people would expect this to happen everywhere,
> despite what the documentation for the option says.

This notes the change of behaviour.

pws

diff --git a/README b/README
index 4d2b6c1..d2b8b69 100644
--- a/README
+++ b/README
@@ -38,10 +38,12 @@ 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.
+Various arithmetic operations have changed, in particular with respect
+to the choice of integer or floating point operations.  The new
+behaviour is intended to be more consistent, but is not compatible with
+the old.
 
-Previously, the modulus operation, `%', implicitly converted the
+1) 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
@@ -57,7 +59,8 @@ New behaviour:
 % print $(( 5.5 % 2 ))
 1.5
 
-Previously, assignments to variables assigned the correct type to
+
+2) 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
@@ -81,6 +84,44 @@ New behaviour:
 % print $var
 2
 
+
+3) Previously, the FORCE_FLOAT option only forced the use of floating
+point in arithmetic expressions for integers constants, i.e. numbers
+typed directly into the expression, but not for variables.  Hence
+an operation involving only integer variables (or string variables
+containing integers) was not forced to be performed with floating point
+arithmetic.  Now, operations involving variables are also forced to
+floating point.  For example:
+
+Old behaviour:
+
+% unsetopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0
+% integer i=1 j=2
+% print $(( i / j ))
+0
+% setopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0.5
+% print $(( i / j ))
+0
+
+New behaviour:
+
+% unsetopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0
+% integer i=1 j=2
+% print $(( i / j ))
+0
+% setopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0.5
+% print $(( i / j ))
+0.5
+
+
 Incompatibilities between 5.0.2 and 5.0.5
 -----------------------------------------
 


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-15 13:34                                       ` Vincent Lefevre
  2015-01-15 13:41                                         ` Vincent Lefevre
@ 2015-01-15 18:32                                         ` ZyX
  2015-01-15 21:57                                           ` Bart Schaefer
  1 sibling, 1 reply; 29+ messages in thread
From: ZyX @ 2015-01-15 18:32 UTC (permalink / raw)
  To: Vincent Lefevre, zsh-workers


15.01.2015, 16:44, "Vincent Lefevre" <vincent@vinc17.net>:
> On 2015-01-15 00:37:43 +0300, ZyX wrote:
>>  14.01.2015, 17:48, "Vincent Lefevre" <vincent@vinc17.net>:
>>>  On 2015-01-14 02:03:33 +0300, ZyX wrote:
>>>>   13.01.2015, 19:01, "Vincent Lefevre" <vincent@vinc17.net>:
>>>>>   In POSIX, it is always an integer division.
>>>>   What?!
>>>>
>>>>   1. How POSIX is related? Zsh is not a POSIX shell and it is not emulation mode that is being discussed here.
>>>  Zsh is partly based on POSIX for compatibility. The big difference
>>>  is the lack of word splitting (unless SH_WORD_SPLIT is set). Otherwise
>>>  I think that one should expect similar behavior, unless there is a
>>>  good reason.
>>>>   2. If this standard is correct: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tagtcjh_15 then it references ISO C standard.
>>>  [...]
>>>>      Where do you see a requirement for `/` to be integer division?
>>>  The context is an integer arithmetic. Thus / is necessarily an
>>>  integer division, like in C with integer types.
>>  No. The context explicitly says that signed long integers or doubles
>>  should be used. Context of the ISO C standard obviously does not say
>>  anything like this.
>
> Wrong. The context of $((...)) is signed long arithmetic. If a shell
> wants to use double's (such as 1.0), that's only an extension.

It is never written in the standard that context is signed long arithmetic. It is only written that signed long integers are the only required types, not the only possible.

>>>  But POSIX doesn't specify the arithmetic evaluation on expressions
>>>  other than signed long integer arithmetic. An implementation that
>>>  decides that $((1.0/2)) gives 17 "as an extension" could still be
>>>  conforming.
>>  Nope, it cannot ever be conforming. POSIX does this by saying that
>>  semantic of operation is the same as in C,
>
> Only for what it specifies.
>>  except that only signed long integers and doubles are allowed.
>
> No, POSIX says "As an extension, the shell may recognize arithmetic
> expressions beyond those listed." and does not specify anything on
> such expressions. $((1.0/2)) is such an arithmetic expression beyond
> those listed.
>
> In particular, it does *not* say that "only signed long integers and
> doubles are allowed". A shell could implement other types (number
> fields or whatever), and specific operators. And note that in such
> an expression, "/" is not necessarily an operator, but could be part
> of a constant.

Standard says that “The arithmetic expression shall be processed according to the rules given in Arithmetic Precision and Operations”. In the referenced section it talks about signed long integers and doubles, neither is forbidden by “the following exceptions”. It as well talks about C rules for arithmetic. So 1.0 is *listed*, but is not *required*. If you want to say POSIX does not list doubles show where it excludes double from the list. Exceptions bullet-list *does not* exclude anything, but selection, iteration and jump statements. All other points are given in a form “feature is not required” or “[of the similar features, I guess] only feature is required” which is not the same as “The arithmetic expression shall be processed according to the rules for signed integers given in …” (in which case doubles indeed were not falling into listed category).

If a shell wants to use double’s it falls into a listed category. But if shell wants to use `//` for always-floating-point division operator then it is what is “beyond those listed”. Zsh math functions are as well, even if they have names from math.h (requirements on such functions are put in the next sub…section (what should something that has lesser then third level called? This whatever is under 1.1.2 subsubsection) which was not referenced in shell standard). This also applies to $(( base#number )) syntax. But not to doubles because they are listed.

The standard *does* say that integer variables and constants shall be implemented as signed long integers and floating-point things should use double (or the equivalent, for both). It is also explicitly said that conversion rules between them are derived from C. So POSIX-compliant $(()) must either not use floating-point values or have double for floating-point values, but it must not have something strange for floating-point values: e.g. lower-precision float or Fraction with two big integers (I mean Fraction class from Python fractions module which basically is a numerator+denominator pair capable of representing any rational number (Python uses big integers for its only integer type)).

>
> --
> Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
> Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Math expression evaluation error?
  2015-01-15 18:32                                         ` ZyX
@ 2015-01-15 21:57                                           ` Bart Schaefer
  0 siblings, 0 replies; 29+ messages in thread
From: Bart Schaefer @ 2015-01-15 21:57 UTC (permalink / raw)
  To: zsh-workers

Guys, this POSIX argument has gone on way too long and with way too much
context being quoted every time somebody replies.  I haven't seen any
suggestion emerge from this that we should be doing anything different
than we alreay decided to do, so unless you're taking this somewhere that
might end in a concrete proposal of some kind, please wrap it up or stop
copying the list.  Thanks.


^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2015-01-15 21:58 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-09 19:46 Math expression evaluation error? jdh
2015-01-09 20:15 ` Peter Stephenson
2015-01-09 21:40   ` jdh
2015-01-09 22:19     ` Ray Andrews
2015-01-09 23:06       ` Lawrence Velázquez
2015-01-09 23:52         ` Ray Andrews
2015-01-10  0:25           ` Bart Schaefer
2015-01-10  7:27             ` Ray Andrews
2015-01-10 16:53               ` Bart Schaefer
2015-01-10 18:48                 ` Ray Andrews
2015-01-10 19:14                   ` Bart Schaefer
2015-01-10 22:21                     ` Ray Andrews
2015-01-11  1:51                       ` Bart Schaefer
2015-01-11  5:10                         ` Ray Andrews
2015-01-12  9:17                           ` Vincent Lefevre
2015-01-12 16:18                             ` ZyX
2015-01-13 16:00                               ` Vincent Lefevre
2015-01-13 23:03                                 ` ZyX
2015-01-14 14:47                                   ` Vincent Lefevre
2015-01-14 21:37                                     ` ZyX
2015-01-15 13:34                                       ` Vincent Lefevre
2015-01-15 13:41                                         ` Vincent Lefevre
2015-01-15 18:32                                         ` ZyX
2015-01-15 21:57                                           ` Bart Schaefer
2015-01-09 22:40     ` Peter Stephenson
2015-01-12 10:55       ` Peter Stephenson
2015-01-14 15:02       ` Vincent Lefevre
2015-01-14 15:38         ` Peter Stephenson
2015-01-15 14:58           ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).