13

Derived from this question : (Java) How does java do modulus calculations with negative numbers?

Anywhere to force PHP to return positive 51?

update
Looking for a configuration setting to fix, instead hard-guessing

Or other math function like bcmath?

updated
Not entire convinced by that java answer, as it does not take account of negative modulus -13+(-64) =?

Community
  • 1
  • 1
ajreal
  • 46,720
  • 11
  • 89
  • 119
  • 1
    updated ... looking for solution without using hard-guessing method – ajreal Dec 10 '10 at 13:38
  • 2
    There is no configuration setting to change how math works in PHP. If there was then it would probably break PHP, which I would imagine uses lots of calculations internally – Gareth Dec 10 '10 at 13:40
  • That's not an intended algorithm. Surprisingly Python and Perl accept it, but PHP doesn't. Use a workaround. Btw, `fmod()` and `bcmod()` and `gmp_mod()` don't either. – mario Dec 10 '10 at 13:46

5 Answers5

16

Anyway, the post you referenced already gave the correct answer:

$r = $x % $n;
if ($r < 0)
{
    $r += abs($n);
}

Where $x = -13 and $n = 64.

Spiny Norman
  • 8,277
  • 1
  • 30
  • 55
7

If GMP is available, you can use gmp_mod

Calculates n modulo d. The result is always non-negative, the sign of d is ignored.

Example:

echo gmp_strval(gmp_mod('-13', '64')); // 51

Note that n and d have to be GMP number resources or numeric strings. Anything else won't work¹

echo gmp_strval(gmp_mod(-13, 64));
echo gmp_mod(-13, 64);

will both return -51 instead (which is a bug).

¹ running the above in this codepad, will produce 51 in all three cases. It won't do that on my development machine.

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • I really wouldn't use the GMP library for this. It's far too heavyweight. The answer below by Spiny Norman is much better. – Richard Smith Oct 16 '20 at 14:00
4

The modulo operation should find the remainder of division of a number by another. But strictly speaking in most mainstream programming languages the modulo operation malfunctions if dividend or/and divisor are negative. This includes PHP, Perl, Python, Java, C, C++, etc.

Why I say malfunction? Because according to mathematic definition, a remainder must be zero or positive.

The simple solution is to handle the case yourself:

if r < 0  then r = r + |divisor|;

|divisor| is the absolute value of divisor.

Another solution is to use a library (as @Gordon pointed). However I wouldn't use a library to handle a simple case like this.

Nylon Smile
  • 8,990
  • 1
  • 25
  • 34
2

I hate using if in this case when you can calculate it right away.

$r = ($x % $n + $n) % $n;

when $n is positive.

Anurat Chapanond
  • 2,837
  • 3
  • 18
  • 31
0

The PHP manual says that

The result of the modulus operator % has the same sign as the dividend — that is, the result of $a % $b will have the same sign as $a. For example

so this is not configurable. Use the options suggested in the question you linked to

Gareth
  • 133,157
  • 36
  • 148
  • 157