Comments (8)
I’ve frequently had the need for a non-zero modulo function, where zmod(a*b, b)
returns b
instead of 0
, e.g. when calculating ordinal indices starting with 1 as in dates. This is easily done with mod(a*b - 1, b) + 1
, except I’m not sure this always behaves as expected for parameters being negative or zero.
PS: Apparently, Mathematica has a generalized modulo function with variable offset d for this: Mod[a, n, d]
.
Math.mod = function ( dividend, divisor, offset = 0 ) {
var remainder = (dividend - offset) % divisor + offset;
if ( remainder * divisor < 0 ) {
remainder += divisor;/*?*/
}
return remainder;
};
(Naively adapted from the code @Andrew-Cottrell had posted.)
from proposal-math-extensions.
can't you maybeZero || b
in that case?
from proposal-math-extensions.
The following implementation, of the suggested function, appears to satisfy the criteria described above.
/**
* A modulo operation that finds the remainder after division of a dividend
* by divisor, using Donald E. Knuth's floored division.
*
* The remainder will have an absolute value less than the absolute
* value of the divisor. Unlike the ECMAScript remainder (%)
* operator, the remainder will have the same sign as the divisor.
*
* @param {number|BigInt} dividend - A finite number.
* @param {number|BigInt} divisor - A non-zero number.
* @return {number|BigInt} The remainder.
* @throws {TypeError} If exactly one of the parameters is a BigInt.
* @throws {RangeError} If the divisor is 0n.
*/
Math.mod = function ( dividend, divisor ) {
/* based on https://github.com/google/closure-library/blob/v20210106/closure/goog/math/math.js#L68 */
var remainder = dividend % divisor;
if ( remainder * divisor < 0 ) {
remainder += divisor;
}
return remainder;
};
/* if either dividend or divisor is not a number, return NaN */
Math.mod( "a", 1 ); // NaN
Math.mod( 1, "a" ); // NaN
Math.mod( NaN, 1 ); // NaN
Math.mod( 1, NaN ); // NaN
/* if divisor is a zero, return NaN or throw RangeError */
Math.mod( 1, 0 ); // NaN
Math.mod( 1, -0 ); // NaN
Math.mod( 1n, 0n ); // RangeError: Division by zero
/* if dividend is a zero, return the dividend */
Math.mod( 0, 1 ); // 0
Math.mod( -0, 1 ); // -0
Math.mod( 0, Infinity ); // 0
Math.mod( 0, -Infinity ); // 0
Math.mod( -0, Infinity ); // -0
Math.mod( -0, -Infinity ); // -0
Math.mod( 0n, 1n ); // 0n
/* if the dividend is an infinity, return NaN */
Math.mod( Infinity, 1 ); // NaN
Math.mod( -Infinity, 1 ); // NaN
/* if the divisor is an infinity with the same sign as the dividend, return the dividend */
Math.mod( 1, Infinity ); // 1
Math.mod( -1, -Infinity ); // -1
/* if the divisor is an infinity with the opposite sign as the dividend, return the divisor */
Math.mod( -1, Infinity ); // Infinity
Math.mod( 1, -Infinity ); // -Infinity
/* integers */
Math.mod( 4, 3 ); // 1
Math.mod( 4n, 3n ); // 1n
Math.mod( 4, -3 ); // -2
Math.mod( 4n, -3n ); // -2n
Math.mod( -4, 3 ); // 2
Math.mod( -4n, 3n ); // 2n
Math.mod( -4, -3 ); // -1
Math.mod( -4n, -3n ); // -1n
/* non-integers */
Math.mod( 5.5, 2 ); // 1.5
Math.mod( 5.5, -2 ); // -0.5
Math.mod( -5.5, 2 ); // 0.5
Math.mod( -5.5, -2 ); // -1.5
Except corner cases, this is the same as
java.lang.Math.floorMod
(integers only)- Python's
%
(modulo) operator - Microsoft Excel's and LibreOffice Calc's
MOD
function - https://google.github.io/closure-library/api/goog.math.html#modulo
- https://mathjs.org/docs/reference/functions/mod.html
- and other modulo operations that use floored division
from proposal-math-extensions.
My concern is that Math.mod
may be an ambiguous name, and there's multiple valid definitions of mod, and there's even another definition not mentioned there which makes use of roundInf
expand
(rounding away from zero, and towards unsigned Infinity).
Even if none of those definitions are ever added (specially modCeil
which is useless compared to modFloor
), we should be aware of them, because maybe someday modEuclid
gets added.
And we have another problem (only if more than 2 definitions are added): Should all be merged into 1 mod
method with a 3rd string
argument to specify the variant? Or should they all be splitted into standalone methods?
Yet another problem is modPow
: should modPow
only use 1 variant? Should it have a 4th arg to specify the variant? Or should it be split in multiple methods?
from proposal-math-extensions.
My concern is that
Math.mod
may be an ambiguous name...
In my own library, I named it floorMod
(following Java's java.lang.Math.floorMod
) to avoid ambiguity by clarifying the rounding mode. However, given Microsoft Excel and LibreOffice Calc use MOD
, it is reasonable to use mod
to mean the floored modulo. Something like modEuclid
could be added, concurrently or later, with a longer name for — what I assume would be — less common use cases.
from proposal-math-extensions.
I agree, seems reasonable considering the "most" standard mod
definition (in mathematics) is defined using floor division
from proposal-math-extensions.
I'd like to add a modulo function, different from standard %. Let's call it Math.mod (x, d).
* if either x or d is not a number, return NaN.; ...
Note that these functions would just coerce their arguments to numbers instead.
from proposal-math-extensions.
Today I learned that what I call "roundInf" is actually named expand
in the official and standard Intl.NumberFormat
API. Here (at the roundingMode
option). In Java, that same rounding mode is named UP
.
I'll open a new Issue about rounding modes.
Update: #28
from proposal-math-extensions.
Related Issues (20)
- [Suggestion] Methods to be added HOT 8
- [Suggestion] Math.mean and Math.roundBy HOT 2
- [Suggestion] Constants to be added HOT 1
- Is it still active? HOT 7
- [Suggestion] Math.lerp and Math.normalize HOT 2
- alternatives to Math.radians and Math.degrees HOT 5
- Math.exp2
- Math.pow should accept Bigints, modulo and pow=-1 HOT 12
- Proposal Math.clamp separately HOT 1
- In the spec draft missed conversion of arguments to numbers
- Repository should be transferred to tc39 organization HOT 2
- Should `factorial` be defined in all or some domains? HOT 2
- Dot product?
- New rounding modes HOT 1
- Bitwise methods HOT 4
- Tuple methods
- `Number.prototype.toByteSize` / `Intl.SizeFormat` HOT 2
- `Math.copysign`? HOT 1
- `Math.MAX_RANDOM_BITS`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from proposal-math-extensions.