算术运算符

还记得学校里学到的基本数学知识吗?就和它们一样。

表格 15-2. 算术运算符

例子名称结果
-$a取反$a 的负值。
$a + $b加法$a 和 $b 的和。
$a - $b减法$a 和 $b 的差。
$a * $b乘法$a 和 $b 的积。
$a / $b除法$a 除以 $b 的商。
$a % $b取模$a 除以 $b 的余数。

除号(“/”)总是返回浮点数,即使两个运算数是整数(或由字符串转换成的整数)也是这样。

注: 取模 $a % $b$a 为负值时的结果也是负值。

参见手册中的数学函数


add a note add a note User Contributed Notes
Jonathon Reinhart
16-Oct-2006 05:11
A very simple yet maybe not obvious use of the modulus (%) operator is to check if an integer is odd or even.
<?php
 
if (($a % 2) == 1)
  { echo
"$a is odd." ;}
  if ((
$a % 2) == 0)
  { echo
"$a is even." ;}
?>

This is nice when you want to make alternating-color rows on a table, or divs.

<?php
 
for ($i = 1; $i <= 10; $i++) {
   if((
$i % 2) == 1//odd
    
{echo "<div class=\"dark\">$i</div>";}
   else 
//even
    
{echo "<div class=\"light\">$i</div>";}
   }
?>
mdirks at gulfstreamcoach dot com
13-Sep-2006 10:01
Quote from TChan's post:
"...But if you're dealing with ints anyway, (a-a%b)/b has no function calls and returns an int, while floor() always returns a float."

 It *explicitly* says in the documentation that the division operator *always* returns a float value *regardless* of the types of the operands. While you may get the "integer part" of the number that way you will technically not get an integer. PHP may not be too strongly typed for the most part, but it's important to make the distinction.

"... if the 'fractional part' of $a/$b is close to 1, then it can round up, and floor($a/$b) will be larger than it should be."

Actually I think you meant *smaller*, not larger... the reason floor($a/$b) isn't absolutely equatable with the integer division of $a and $b is explained mainly at http://us3.php.net/float . By the look of things, any number with a loss of precision will be truncated instead of rounded. This would at least make sense in the big picture since truncation is more consistant than rounding.
T Chan
20-Aug-2006 12:28
Please note that floor($a/$b) is not the same as integer division. if the 'fractional part' of $a/$b is close to 1, then it can round up, and floor($a/$b) will be larger than it should be. The example is a bit contrived though (and printf doesn't print enough digits).

<?php printf("%f\n",$a = 9007199254740991); // 9007199254740991.000000
printf("%f\n", $b = $a * 3.0); //27021597764222970.000000, the actual value stored ends in 2 while the true value ends in 3
printf("%f\n", $b/$a - 3.0); //0.000000
printf("%f\n", $b - 2*$a - $a); //-1.000000
printf("%f\n",fmod($b,$a)); //9007199254740990.000000 fmod agrees too
?>

Admittedly it's a bit 'specially-crafted', but it just goes to show. I believe it does work for integers that can be exactly represented in FP. But if you're dealing with ints anyway, (a-a%b)/b has no function calls and returns an int, while floor() always returns a float.
Ulf Wostner
05-Aug-2006 03:13
# There are several natural ways to define the mod operator for integers.
# Requirement:  If mod(k, m) = r, then k and r differ by a multiple of m.

# For m=7, think days-of-the-week.  Both mod(13, 7) = 6 and mod(13, 7) = -1
# satisfy the requirement. Six days from today, or one day ago, are the same DOW.

# There are several natural ways to define the mod operator for integers.
# Requirement:  If mod(k, m) = r, then k and r differ by a multiple of m.

# For m=7, think days-of-the-week.  Both mod(13, 7) = 6 and mod(13, 7) = -1
# satisfy the requirement. Six days from today, or one day ago, are the same DOW.

# Here are four mod operators:

# 1. mod_php.
# Same as the built-in PHP function, so mod_php($k,$m) == ($k % $m).
# A negative value might jolt a programmer using it for array index.

function mod_php($k, $m) {return $k % $m; }

# 2. Standard math definition.
# Nice. But, if for some reason m is negative, be prepared for negative values.

function mod_math($k, $m) { return ($k - $m * floor($k/$m)); }

# 3. Smallest absolute value.
# Sometimes convenient for large integers, making good use of the sign-bit.
# Also, for mere humans, "-2 months from May", might be easier than "10 months from May".

function mod_min($k, $m) {
$r = mod_pos($k, $m);
if($r > abs($m)/2) $r -= abs($m);
return $r;
}

# 4. Smallest non-negative value.
# Maybe closest to the concept that mod is the remainder when dividing $k by $m.

function mod_pos($k, $m) { return ($k - abs($m) * floor($k/abs($m))); }

# This table compares the four functions.

k    m  mod_php mod_math  mod_min  mod_pos

18    7      4      4      -3          4
17    7      3      3      3          3
16    7      2      2      2          2

-16    7    -2      5      -2          5
-17    7    -3      4      -3          4
-18    7    -4      3      3          3

18    -7    4      -3      -3          4
17    -7    3      -4      3          3
16    -7    2      -5      2          2

-16    -7    -2      -2      -2        5
-17    -7    -3      -3      -3        4
-18    -7    -4      -4      3        3
bxm AT cs d0t nott d0t ac d0t uk
06-Jun-2006 07:06
An implementation of the classical modulus operator (as in mathematics or Java). An alternative to the one given below, which was more elegant. This implementation maybe more efficient?

// Computes...
// Mathematics: $a (mod $b)
// Java: $a % $b
function modulus( $a, $b )
{
   if( $a < 0 )
   {
       return $b - ( abs( $a ) % $b );
   }
   else
   {
       return $a % $b;
   }
}
andr3a at 3site dot it
05-Jun-2006 08:14
[ops ... wrong example :D]
just a note about module, it works only with integers.

<?php
$a
= pow(2, 31);
$b = ($a / 2) - 1;
echo
implode('<br />', array(
  
$a + $b, // OK => 3221225472
  
$a - $b, // OK => 1073741825
  
$a * $b, // OK => 2.3058430070662E+018
  
$a / $b, // OK => 2.0000000018626
  
$a % $b  // WTF ? => -2
));
?>

maybe bc_mod with a string cast should be a solution

bc_mod((string)pow(2,31), (pow(2,31)/2)-1)
shmee35 at hotmail dot com
15-Dec-2005 07:00
Note that constructs which evaluate to 0 (such as empty strings, false, or an explicit NULL) will be treated as 0 in a arithmetic operation. Therefore:
<?php
echo 5*"", '<br>';
echo
5+false, '<br>';
echo
5/NULL, '<br>';
?>
Will produce:
0
5
Warning: Division by zero
pww8 at cornell dot edu
18-Aug-2005 05:25
It appears floating-point infinity (INF) is not returned from divide by zero (in PHP 5.0.0).  Instead a warning is given and Boolean FALSE is returned.

I searched the various manuals and did not find relevant explanation, so am adding this.
Gemini6Ice
13-Aug-2005 06:59
For integer division, just use floor($a / $b).
rz at daimi dot au dot dk
05-Apr-2005 08:04
This is a really simple observation.
There is no integer division operator. But if you need to divide by a power of 2, you can use the right-shift operator instead. 257/32 gives 8.03125, but 257>>5 gives 8.
areshankar at gmail dot com
17-Mar-2005 06:40
Most of the mail services/bulletin boards display the time when the message was posted or the mail was received in the  form  - 3 days ago, 15 mins ago etc.

Here is  a nifty little PHP function which does the same by basically  combining the usage of "/" and "%" operators.

You need to pass the unix timestamp of the time when the message was posted to the function.

function intervalCalc($postedtime)
{
   $now = time();
   $interval_secs = $now  - $postedtime;
  
   if ($interval_secs > 86400)
   {
       $interval = (($interval_secs - ($interval_secs%86400))/86400);
      
       $interval.= " days ago";
   }
   elseif ($interval_secs > 3600)
   {
       $interval = ($interval_secs - ($interval_secs%3600)/3600);
      
       $interval.= " hours ago";
   }
   elseif ($interval_secs > 60)
   {
       $interval = ($interval_secs - ($interval_secs%60)/60);
      
       $interval.= " minutes ago";
   }
  
   return  $interval;
  
}
sputnik13 at gmail dot com
14-Feb-2005 10:49
I just had to make a comment about gilthans' use of the bitwise xor operator (^)...  I'm guessing from the line if(($x < 0 ^ $y < 0) && $x != 0) that he wants to verify that only x or only y is less than 0 AND x != 0...  Bitwise operators should not be used for truth values like this, that's what xor is for.
justin at koivi dot com
26-Jan-2005 05:08
A note about the documentation on this page that I found while teaching a PHP class:

The above statment: "The division operator ("/") returns a float value anytime, even if the two operands are integers (or strings that get converted to integers)." is NOT TRUE.

Take the following:
<?php
$a
=5;
$b=10;
$c=$b/$a;
$d=10/5;
var_dump($c);
var_dump($d);
var_dump($b/$a);
var_dump(10/5);
?>
All 4 instances will print "int(2)"

Therefore, the division operator "/" returns an integer value if the numbers are evenly divisible AND they are both integers (or strings that have been converted to integer values).
no at email dot com
14-Jan-2005 05:08
If you need "div" function like in pascal ( 123 div 10 == 12) you can try this:
$number "div" 10 = ($number-($number % 10)) / 10;
jphansen at uga dot edu
07-Jan-2005 02:12
If the second operand of modulus is of a precision type, modulus will return a boolean instead of a numeric type.
gilthans at gmail dot com
21-Dec-2004 05:13
Me and a few friends were talking about how math works in coding languages, and after a while of discussion, we started wondering how does the sqrt() function works, and how does the division work, using only addition, substraction and multiplication (because that could be easily done using only addition).
I have best knowledge in PHP, so I had my shot at division, and a while of testing proved that my code works. I'm posting this here for the curious, even though the normal PHP division works 7 times faster, so I think there is some way of making my code more efficient.
divide($x, $y, $a, 0) is similar to number_format($x/$y, $a);, and divide($x, $y, $a, 1) is similar to Array(floor($x/$y), $x%$y).
<?php
function divide($x, $y, $a=6, $z=false){
  
// returns $x/$y
  
$t = '';
   if(
$y == 0)
   return
0;
   if((
$x < 0 ^ $y < 0) && $x != 0)
  
$t = '-';
  
$x = abs($x);
  
$y = abs($y);
  
$in = 0;
   while((
$in+1)*$y <= $x)
      
$in++;
  
$r = $x-($in*$y);
   if(
$z)
   return Array(
$in, $r);
  
$d = '';
  
$c = 0;
   while(
$r != 0 && $c < $a){
   list(
$u, $r) = divide($r*10, $y, $a, 1);
  
$c++;
   if(
$c >= $a){
      
$b = divide($r*10, $y, $a, 1);
      
$u += ($b[0] > 4) ? 1 : 0;
   }
  
$d .= $u;
   }
   return
intval($t.$in.(($d != '') ? ".".$d : ""));
}
?>
adam.pippin at accesscomm dot ca
03-Dec-2004 05:15
To factor a number:

<?php

function factornumber($number)
{
   for (
$i=1; $i<=($number/2); $i++)
   {
       if (
$number % $i == 0)
       {
           echo
"$i * ".($number/$i)." = $number\n";
       }
   }
}

factornumber(50);

?>

That script outputs:

1 * 50 = 50
2 * 25 = 50
5 * 10 = 50
10 * 5 = 50
25 * 2 = 50

As you may notice, it makes no attempts at removing duplicates (eg: 5*10 and 10*5), although it would be trivial to make it do so.
glenn at benge dot co dot nz
06-Oct-2004 02:28
a real simple method to reset an integer to a the next lowest multiple of a divisor

$startSeq = $startSeq - ($startSeq % $entriesPerPage);

if $startSeq was already a multiple, then " $startSeq % $entriesPerPage " will return 0 and $startSeq will not change.
arjini at gmail dot com
09-Sep-2004 12:48
When dealing purely with HTML, especially tables, or other things in "grids"  the modulous operator is really useful for splitting up the data with a seperator.

This snippet reads any gif files from the directory the script is in, prints them out and puts in a break every 5th image.

<?php
   $d
= dir('./');
  
$i = 0;
   while(
false !== ($e = $d->read())){
       if(
strpos($e,'.gif')){
           ++
$i;
           echo
'<img src="'.$e.'"/>'.chr(10);
           if(!(
$i%5))
               echo
'<br/>';
       }
   }
?>

For tables just put </tr><tr> in place of the break.
csaba at alum dot mit dot edu
16-May-2004 08:32
The function below is not a replacement for http://php.net/fmod  Rather, it is the classic (mathematician's) modulo where the resultant value is always non-negative, in the range [0,$base).  For example, mod(-9,7) => 5.  When both arguments are integers, you get the classic notion of the % operator.

function mod($num, $base) {
   return ($num - $base*floor($num/$base)); }

Csaba Gabor
info at sima-pc dot com
02-May-2004 05:48
Note that operator % (modulus) works just with integers (between -214748348 and 2147483647) while fmod() works with short and large numbers.

Modulus with non integer numbers will give unpredictable results.
php AT internethoofdkantoor.nl
13-Jan-2004 08:15
For the mathematicians among us:
The mod operator % works a bit differently than in mathematics (e.g. in group theory), in that negative remainders aren't represented by their positive equivalence classes, as is common in mathematics.

An example:
-1%7 returns -1, instead of 6.

it depends a bit on how you interpret 'remainder of a division', i.e. if you want the remainder to be always positive.
soren at byu dot edu
20-Nov-2003 11:49
Exponentiation doesn't use ^ or ** as you might be used to with other languages.  To calculate "z equals y to the x" use:

$z = pow(y,x)
darnell at uga dot edu
29-Oct-2003 11:57
Also, when automatically converting floats to integers, PHP truncates them rather than rounding.  So in the previous note, 2.4 gets truncated to 2 before the modulus operator is applied.
todd at magnifisites dot com
17-Oct-2003 07:22
There isn't much detail in the PHP Manual regarding the PHP modulus operator (%).  It seems as though the PHP modulus operator (%) works on integer operands. If PHP operates like Perl, then the modulus operator (%) converts its operands to integers before finding the remainder according to integer division.  Testing seems to prove the theory:

<?php
$dividend
= 7;
$divisor = 2.4;
print
$dividend%$divisor; // prints 1
print fmod($dividend, $divisor); // prints 2.2
?>