Hi folks,

As part of fixing GROOVY-10800, I was planning to make the behavior
for the "%" operator for BigInteger be consistent with our other data
types (and with Java).

Basically, there is a distinction between "remainder" and "modulo" for
negative numbers.
For the expression "numerator op divisor", they will be the same for
positive numbers but for negative numbers, "remainder" will return a
negative number for a negative numerator while "modulo" will always
return a number "0 <= result < divisor". You can get one from the
other by adding the divisor to a negative result from "remainder".

What is sometimes a little confusing is that the "remainder" operator
(%) is often informally referred to as the "mod" operator (since they
are the same for positives). Indeed, we use "mod" as the name of the
method to use for operator overloading purposes.

Currently the behavior is:

def nums = [-10, -10L, -10f, -10d, -10G, -10.0G]
assert nums.collect{ it % 3 } == [-1, -1, -1f, -1d, 2G, -1.0G]

(Note: The BigDecimal result relies on GROOVY-10786, so currently only
in master.)

Changing the behavior is easy (albeit breaking for negatives) but
there is a knock on consequence. Since we use "mod" as our method for
operator overloading, the BigInteger "mod" method is then no longer
available.

For Groovy 5, we could go and rename our operator overloading method
from "mod" to "remainder" or some such but it is quite an intrusive
change.

There is a workaround which we could document:

def negTen = -10G
assert 2G == negTen.modPow(1, 3)

And/or we could provide a "modulo" extension method on BigInteger to allow:

assert 2G == negTen.modulo(3)

This last approach was what I was thinking of doing.

Thoughts?

Cheers, Paul.

Reply via email to