Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Math expression evaluation error?



15.01.2015, 16:44, "Vincent Lefevre" <vincent@xxxxxxxxxx>:
> On 2015-01-15 00:37:43 +0300, ZyX wrote:
>>  14.01.2015, 17:48, "Vincent Lefevre" <vincent@xxxxxxxxxx>:
>>>  On 2015-01-14 02:03:33 +0300, ZyX wrote:
>>>>   13.01.2015, 19:01, "Vincent Lefevre" <vincent@xxxxxxxxxx>:
>>>>>   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@xxxxxxxxxx> - 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)



Messages sorted by: Reverse Date, Date, Thread, Author