Modulo Operator %%

classic Classic list List threaded Threaded
26 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Re: Modulo Operator %%

Matthew Morgan
Isiah, thank you for composing this proposal.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modulo Operator %%

peter miller
In reply to this post by Isiah Meadows-2
Hi,

+1 for _at_least_ having `Math.mod()`

And here's a reason why:

The code `mod = (x,y) => ( ( x % y ) + y ) % y` is not only slow but  
inaccurate. For example, for `mod( -249825144445569.97,  
-2022673516699079.8)` gives `-249825144445569.75` (Chrome Version  
77.0.3865.35) instead of `-249825144445569.97`

I then switched to `mod = (x,y) => x - Math.floor( x / y ) * y` which  
gives an accurate answer, and is faster.

But, on a hunch that flow control would be faster than arithmetic, I  
devised this:

```
mod = (x,y) => {
   const z = x % y;
   return  (y >= 0 && z >= 0 ) || ( y < 0 && z <= 0 ) ? z : y + z;
}
```
And that is _sometimes_ the fastest approach -- assuming I haven't screwed  
up the maths; cf  https://jsbench.me/lrjze7oqv9/2 Although it does seem to  
depend on the numbers - with the `Math.floor()` approach sometimes coming  
out faster.

And this all neglects BigInts, Infinites, NaNs, and signed zeroes.

So this isn't a trivial function to polyfill. And, for that reason alone,  
it should be in the standard. (And if we get it in Math, and convince  
people to use it, then the pressure for a more ergonomic solution will  
increase.)

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modulo Operator %%

kdex
Reply inline.

On Friday, August 16, 2019 5:50:40 PM CEST peter miller wrote:

> Hi,
>
> +1 for _at_least_ having `Math.mod()`
>
> And here's a reason why:
>
> The code `mod = (x,y) => ( ( x % y ) + y ) % y` is not only slow but
> inaccurate. For example, for `mod( -249825144445569.97,
> -2022673516699079.8)` gives `-249825144445569.75` (Chrome Version
> 77.0.3865.35) instead of `-249825144445569.97`
>
> I then switched to `mod = (x,y) => x - Math.floor( x / y ) * y` which
> gives an accurate answer, and is faster.
>
> But, on a hunch that flow control would be faster than arithmetic, I
> devised this:
>
> ```
> mod = (x,y) => {
>    const z = x % y;
>    return  (y >= 0 && z >= 0 ) || ( y < 0 && z <= 0 ) ? z : y + z;
> }
> ```
> And that is _sometimes_ the fastest approach -- assuming I haven't screwed
> up the maths; cf  https://jsbench.me/lrjze7oqv9/2 Although it does seem to
> depend on the numbers - with the `Math.floor()` approach sometimes coming
> out faster.
>
> And this all neglects BigInts, Infinites, NaNs, and signed zeroes.
Most, if not all, functions on the `Math` prototype can't handle `BigInt`, but
that's a separate issue.

While it would be nice if `Math.mod` supported that, another `Math` proposal
could spec that along with fixes for all the other methods.

For now, it should be good enough if we had a modulo operation at all.

>
> So this isn't a trivial function to polyfill. And, for that reason alone,
> it should be in the standard. (And if we get it in Math, and convince
> people to use it, then the pressure for a more ergonomic solution will
> increase.)
>
> Peter
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Modulo Operator %%

Alex Gordon
In reply to this post by Isiah Meadows-2
Code that uses % is often surprisingly buggy. For example even a simple function such as this is broken if n is negative:

function isOdd(n) {
    return n % 2 === 1;
}

isOdd(-3) // false

The same is not true in other programming languages. The same in Python works just fine:

def isOdd(n):
    return n % 2 == 1

isOdd(-3) // true

The advantage of an operator over a function is that it allows us to say to people who are new to JS: "Always use %% instead of % unless you have a good reason". Just the same as we say "Always use === instead of == unless you have a good reason".


On Thu, Aug 15, 2019 at 10:01 PM Isiah Meadows <[hidden email]> wrote:
BTW, I just wrote up a more precise, formalized proposal over here:
https://github.com/isiahmeadows/proposal-divisor-dependent-modulo/,
and I'd be more than willing to work with a TC39 champion on it. I
personally prefer syntax (pretty strongly), but I'm not beholden to
it.

I do feel the semantics are simple enough it'd be okay to lower it to
syntax, and it naturally just glides right in. I find it *very* odd
that some languages use a simple operator `%` or relatively short
function for remainder keeping the sign of the dividend but relegate
the version keeping the sign of the divisor (the more useful and
intuitive of them) to a much more verbose function call. Of all
Wikipedia lists in https://en.wikipedia.org/wiki/Modulo_operation,
here's the four that do this currently - all but one expose an
operator for the first:

- Fortran: `mod` for dividend-dependent, `modulo` for divisor-dependent
- Julia: `%`/`rem` for dividend-dependent, `mod` for divisor-dependent
- Java: `%` for dividend-dependent, `Math.floorMod` for divisor-dependent
- XBase++: `%` for dividend-dependent, `Mod` for divisor-dependent

And it's worth noting most other languages (including some end
user-oriented ones) that show a syntactic preference to one or the
other expose a simpler one where the sign matches the divisor, a more
complicated one where the sign matches the dividend. For a variety of
examples:

- Ruby: `%`/`modulo` for divisor-dependent, `remainder` for dividend-dependent
- SML: `mod` for divisor-dependent, `Int.rem` for dividend-dependent
- Elm: `modBy` for divisor-dependent, `remainderBy` for dividend-dependent
- Euphoria: `mod` for divisor-dependent, `remainder` for dividend-dependent
- Python: `%` for divisor-dependent, `math.fmod` for dividend-dependent
- Smalltalk: `\\` for divisor-dependent, `rem:` for dividend-dependent

And of course, many don't even expose a type of modulo where the sign
matches the divisor. For some examples:

- APL
- LibreOffice/Excel
- Lua
- Perl
- Mathematica
- PL/I
- TCL

There's also Dart, a relatively new language which defaults to
non-negative always.

This relatively long list of languages, *despite* C's heritage and
semantics being inherited in much of them, makes me question using a
function for this, and there would need to be a *lot* of FUD to get
people to use the function more than the operator.

So this is why I would prefer an operator as opposed to syntax for this.

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com

On Thu, Aug 15, 2019 at 3:58 PM Jordan Harband <[hidden email]> wrote:
>
> Static functions don't have the same risk as prototype functions; `Math.mod` would make sense to add.
>
> One suggestion, though, would be to try to add the API method first, and look at usage for awhile before trying to add the syntax.
>
> On Thu, Aug 15, 2019 at 10:12 AM Andrea Giammarchi <[hidden email]> wrote:
>>
>> To me there's no risk, as MooTools, Prototype, and Scriptacolous are both things of the past, and never implemented Math.mod ... so, with that approach, custom transpiling functions are more dangerous, as somebody might have implemented `%%` already for other purposes, and we break Babel outcome adding new syntax anyway ... the smoosh accident, is the equivalent of custom Babel utilities these days.
>>
>> Look at TypeScript and the private class fields, if you want to compare new syntax instead
>>
>> On Thu, Aug 15, 2019 at 4:50 PM Michael Haufe <[hidden email]> wrote:
>>>
>>> Thursday, August 15, 2019 2:47 AM, Andrea Giammarchi wrote:
>>>
>>>
>>>
>>> > FWIW another disadvantage is that operators cannot be polyfilled, so it'll take forever for those not using transpilers to adopt these, while having a `Math,mod` would work right away
>>>
>>>
>>>
>>>
>>>
>>> With such an approach there is risk of another ‘smooshgate’ [1][2]. There is nothing stopping those developers from using a function anyway to bridge the gap if they can’t or won’t use a compiler. This is already the current state of affairs.
>>>
>>>
>>>
>>> [1] https://developers.google.com/web/updates/2018/03/smooshgate
>>>
>>> [2] https://adamsilver.io/articles/the-disadvantages-of-javascript-polyfills/
>>>
>>>
>>>
>>> Michael
>>
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modulo Operator %%

Isiah Meadows-2
BTW, that very example is something I cover in my proposal's
introduction. It's also part of why I want an operator - this is one
of the few times where spreading FUD *is* a good idea IMHO.
https://github.com/isiahmeadows/proposal-divisor-dependent-modulo/

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com
On Fri, Aug 16, 2019 at 12:33 PM Alex Gordon <[hidden email]> wrote:

>
> Code that uses % is often surprisingly buggy. For example even a simple function such as this is broken if n is negative:
>
> function isOdd(n) {
>     return n % 2 === 1;
> }
>
> isOdd(-3) // false
>
> The same is not true in other programming languages. The same in Python works just fine:
>
> def isOdd(n):
>     return n % 2 == 1
>
> isOdd(-3) // true
>
> The advantage of an operator over a function is that it allows us to say to people who are new to JS: "Always use %% instead of % unless you have a good reason". Just the same as we say "Always use === instead of == unless you have a good reason".
>
>
> On Thu, Aug 15, 2019 at 10:01 PM Isiah Meadows <[hidden email]> wrote:
>>
>> BTW, I just wrote up a more precise, formalized proposal over here:
>> https://github.com/isiahmeadows/proposal-divisor-dependent-modulo/,
>> and I'd be more than willing to work with a TC39 champion on it. I
>> personally prefer syntax (pretty strongly), but I'm not beholden to
>> it.
>>
>> I do feel the semantics are simple enough it'd be okay to lower it to
>> syntax, and it naturally just glides right in. I find it *very* odd
>> that some languages use a simple operator `%` or relatively short
>> function for remainder keeping the sign of the dividend but relegate
>> the version keeping the sign of the divisor (the more useful and
>> intuitive of them) to a much more verbose function call. Of all
>> Wikipedia lists in https://en.wikipedia.org/wiki/Modulo_operation,
>> here's the four that do this currently - all but one expose an
>> operator for the first:
>>
>> - Fortran: `mod` for dividend-dependent, `modulo` for divisor-dependent
>> - Julia: `%`/`rem` for dividend-dependent, `mod` for divisor-dependent
>> - Java: `%` for dividend-dependent, `Math.floorMod` for divisor-dependent
>> - XBase++: `%` for dividend-dependent, `Mod` for divisor-dependent
>>
>> And it's worth noting most other languages (including some end
>> user-oriented ones) that show a syntactic preference to one or the
>> other expose a simpler one where the sign matches the divisor, a more
>> complicated one where the sign matches the dividend. For a variety of
>> examples:
>>
>> - Ruby: `%`/`modulo` for divisor-dependent, `remainder` for dividend-dependent
>> - SML: `mod` for divisor-dependent, `Int.rem` for dividend-dependent
>> - Elm: `modBy` for divisor-dependent, `remainderBy` for dividend-dependent
>> - Euphoria: `mod` for divisor-dependent, `remainder` for dividend-dependent
>> - Python: `%` for divisor-dependent, `math.fmod` for dividend-dependent
>> - Smalltalk: `\\` for divisor-dependent, `rem:` for dividend-dependent
>>
>> And of course, many don't even expose a type of modulo where the sign
>> matches the divisor. For some examples:
>>
>> - APL
>> - LibreOffice/Excel
>> - Lua
>> - Perl
>> - Mathematica
>> - PL/I
>> - TCL
>>
>> There's also Dart, a relatively new language which defaults to
>> non-negative always.
>>
>> This relatively long list of languages, *despite* C's heritage and
>> semantics being inherited in much of them, makes me question using a
>> function for this, and there would need to be a *lot* of FUD to get
>> people to use the function more than the operator.
>>
>> So this is why I would prefer an operator as opposed to syntax for this.
>>
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>> www.isiahmeadows.com
>>
>> On Thu, Aug 15, 2019 at 3:58 PM Jordan Harband <[hidden email]> wrote:
>> >
>> > Static functions don't have the same risk as prototype functions; `Math.mod` would make sense to add.
>> >
>> > One suggestion, though, would be to try to add the API method first, and look at usage for awhile before trying to add the syntax.
>> >
>> > On Thu, Aug 15, 2019 at 10:12 AM Andrea Giammarchi <[hidden email]> wrote:
>> >>
>> >> To me there's no risk, as MooTools, Prototype, and Scriptacolous are both things of the past, and never implemented Math.mod ... so, with that approach, custom transpiling functions are more dangerous, as somebody might have implemented `%%` already for other purposes, and we break Babel outcome adding new syntax anyway ... the smoosh accident, is the equivalent of custom Babel utilities these days.
>> >>
>> >> Look at TypeScript and the private class fields, if you want to compare new syntax instead
>> >>
>> >> On Thu, Aug 15, 2019 at 4:50 PM Michael Haufe <[hidden email]> wrote:
>> >>>
>> >>> Thursday, August 15, 2019 2:47 AM, Andrea Giammarchi wrote:
>> >>>
>> >>>
>> >>>
>> >>> > FWIW another disadvantage is that operators cannot be polyfilled, so it'll take forever for those not using transpilers to adopt these, while having a `Math,mod` would work right away
>> >>>
>> >>>
>> >>>
>> >>>
>> >>>
>> >>> With such an approach there is risk of another ‘smooshgate’ [1][2]. There is nothing stopping those developers from using a function anyway to bridge the gap if they can’t or won’t use a compiler. This is already the current state of affairs.
>> >>>
>> >>>
>> >>>
>> >>> [1] https://developers.google.com/web/updates/2018/03/smooshgate
>> >>>
>> >>> [2] https://adamsilver.io/articles/the-disadvantages-of-javascript-polyfills/
>> >>>
>> >>>
>> >>>
>> >>> Michael
>> >>
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> [hidden email]
>> >> https://mail.mozilla.org/listinfo/es-discuss
>> >
>> > _______________________________________________
>> > es-discuss mailing list
>> > [hidden email]
>> > https://mail.mozilla.org/listinfo/es-discuss
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Modulo Operator %%

Cyril Auburtin
Another typical example:

```js
const normalizeHue = hue => (((hue % 360) + 360) % 360) / 360; // phew..

// would become:
const normalizeHue = hue => (hue %% 360) / 360;
```


On Sat, Aug 17, 2019 at 9:54 PM Isiah Meadows <[hidden email]> wrote:
BTW, that very example is something I cover in my proposal's
introduction. It's also part of why I want an operator - this is one
of the few times where spreading FUD *is* a good idea IMHO.
https://github.com/isiahmeadows/proposal-divisor-dependent-modulo/

-----

Isiah Meadows
[hidden email]
www.isiahmeadows.com
On Fri, Aug 16, 2019 at 12:33 PM Alex Gordon <[hidden email]> wrote:
>
> Code that uses % is often surprisingly buggy. For example even a simple function such as this is broken if n is negative:
>
> function isOdd(n) {
>     return n % 2 === 1;
> }
>
> isOdd(-3) // false
>
> The same is not true in other programming languages. The same in Python works just fine:
>
> def isOdd(n):
>     return n % 2 == 1
>
> isOdd(-3) // true
>
> The advantage of an operator over a function is that it allows us to say to people who are new to JS: "Always use %% instead of % unless you have a good reason". Just the same as we say "Always use === instead of == unless you have a good reason".
>
>
> On Thu, Aug 15, 2019 at 10:01 PM Isiah Meadows <[hidden email]> wrote:
>>
>> BTW, I just wrote up a more precise, formalized proposal over here:
>> https://github.com/isiahmeadows/proposal-divisor-dependent-modulo/,
>> and I'd be more than willing to work with a TC39 champion on it. I
>> personally prefer syntax (pretty strongly), but I'm not beholden to
>> it.
>>
>> I do feel the semantics are simple enough it'd be okay to lower it to
>> syntax, and it naturally just glides right in. I find it *very* odd
>> that some languages use a simple operator `%` or relatively short
>> function for remainder keeping the sign of the dividend but relegate
>> the version keeping the sign of the divisor (the more useful and
>> intuitive of them) to a much more verbose function call. Of all
>> Wikipedia lists in https://en.wikipedia.org/wiki/Modulo_operation,
>> here's the four that do this currently - all but one expose an
>> operator for the first:
>>
>> - Fortran: `mod` for dividend-dependent, `modulo` for divisor-dependent
>> - Julia: `%`/`rem` for dividend-dependent, `mod` for divisor-dependent
>> - Java: `%` for dividend-dependent, `Math.floorMod` for divisor-dependent
>> - XBase++: `%` for dividend-dependent, `Mod` for divisor-dependent
>>
>> And it's worth noting most other languages (including some end
>> user-oriented ones) that show a syntactic preference to one or the
>> other expose a simpler one where the sign matches the divisor, a more
>> complicated one where the sign matches the dividend. For a variety of
>> examples:
>>
>> - Ruby: `%`/`modulo` for divisor-dependent, `remainder` for dividend-dependent
>> - SML: `mod` for divisor-dependent, `Int.rem` for dividend-dependent
>> - Elm: `modBy` for divisor-dependent, `remainderBy` for dividend-dependent
>> - Euphoria: `mod` for divisor-dependent, `remainder` for dividend-dependent
>> - Python: `%` for divisor-dependent, `math.fmod` for dividend-dependent
>> - Smalltalk: `\\` for divisor-dependent, `rem:` for dividend-dependent
>>
>> And of course, many don't even expose a type of modulo where the sign
>> matches the divisor. For some examples:
>>
>> - APL
>> - LibreOffice/Excel
>> - Lua
>> - Perl
>> - Mathematica
>> - PL/I
>> - TCL
>>
>> There's also Dart, a relatively new language which defaults to
>> non-negative always.
>>
>> This relatively long list of languages, *despite* C's heritage and
>> semantics being inherited in much of them, makes me question using a
>> function for this, and there would need to be a *lot* of FUD to get
>> people to use the function more than the operator.
>>
>> So this is why I would prefer an operator as opposed to syntax for this.
>>
>> -----
>>
>> Isiah Meadows
>> [hidden email]
>> www.isiahmeadows.com
>>
>> On Thu, Aug 15, 2019 at 3:58 PM Jordan Harband <[hidden email]> wrote:
>> >
>> > Static functions don't have the same risk as prototype functions; `Math.mod` would make sense to add.
>> >
>> > One suggestion, though, would be to try to add the API method first, and look at usage for awhile before trying to add the syntax.
>> >
>> > On Thu, Aug 15, 2019 at 10:12 AM Andrea Giammarchi <[hidden email]> wrote:
>> >>
>> >> To me there's no risk, as MooTools, Prototype, and Scriptacolous are both things of the past, and never implemented Math.mod ... so, with that approach, custom transpiling functions are more dangerous, as somebody might have implemented `%%` already for other purposes, and we break Babel outcome adding new syntax anyway ... the smoosh accident, is the equivalent of custom Babel utilities these days.
>> >>
>> >> Look at TypeScript and the private class fields, if you want to compare new syntax instead
>> >>
>> >> On Thu, Aug 15, 2019 at 4:50 PM Michael Haufe <[hidden email]> wrote:
>> >>>
>> >>> Thursday, August 15, 2019 2:47 AM, Andrea Giammarchi wrote:
>> >>>
>> >>>
>> >>>
>> >>> > FWIW another disadvantage is that operators cannot be polyfilled, so it'll take forever for those not using transpilers to adopt these, while having a `Math,mod` would work right away
>> >>>
>> >>>
>> >>>
>> >>>
>> >>>
>> >>> With such an approach there is risk of another ‘smooshgate’ [1][2]. There is nothing stopping those developers from using a function anyway to bridge the gap if they can’t or won’t use a compiler. This is already the current state of affairs.
>> >>>
>> >>>
>> >>>
>> >>> [1] https://developers.google.com/web/updates/2018/03/smooshgate
>> >>>
>> >>> [2] https://adamsilver.io/articles/the-disadvantages-of-javascript-polyfills/
>> >>>
>> >>>
>> >>>
>> >>> Michael
>> >>
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> [hidden email]
>> >> https://mail.mozilla.org/listinfo/es-discuss
>> >
>> > _______________________________________________
>> > es-discuss mailing list
>> > [hidden email]
>> > https://mail.mozilla.org/listinfo/es-discuss
>> _______________________________________________
>> es-discuss mailing list
>> [hidden email]
>> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12