算术运算符

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

算术运算符
例子 名称 结果
-$a 取反 $a 的负值。
$a + $b 加法 $a$b 的和。
$a - $b 减法 $a$b 的差。
$a * $b 乘法 $a$b 的积。
$a / $b 除法 $a 除以 $b 的商。
$a % $b 取模 $a 除以 $b 的余数。
$a ** $b Exponentiation Result of raising $a to the $b'th power. Introduced in PHP 5.6.

除法运算符总是返回浮点数。只有在下列情况例外:两个操作数都是整数(或字符串转换成的整数)并且正好能整除,这时它返回一个整数。

取模运算符的操作数在运算之前都会转换成整数(除去小数部分)。

取模运算符 % 的结果和被除数的符号(正负号)相同。即 $a % $b 的结果和 $a 的符号相同。例如:

<?php

echo (3)."\n";           // prints 2
echo (% -3)."\n";          // prints 2
echo (-3)."\n";          // prints -2
echo (-% -3)."\n";         // prints -2

?>

参见手册中的数学函数

User Contributed Notes

vike2000 at gmail dot com 18-Oct-2019 01:20
With % (modulo), it looks like php uses the C operator (apart from some sanity-checks), according to following `awk` command, getting the relevant lines of arbitrary commits (dbb462db5d and 04d5086578 for me) in github.com/php/php-src:

$ awk '!F[0]&&/expr '\''%'\'' expr/{p()} !F[0]&&/case ZEND_MOD/{p();F[0]=1;F[1]="return"} !F[0]&&/mod_function\(.*\)/{p();F[0]=2;F[1]="ZVAL_LONG"} '$(: function p for printing and array F for finding in files follows: )' F[0]&&match($0,F[1])&&1==F[0]--{p();delete F;nextfile}function p(){print FILENAME":"FNR":\t"$0}' Zend/zend_{language_parser.y,{opcode,operators}.c}
Zend/zend_language_parser.y:939:        |    expr '%' expr     { $$ = zend_ast_create_binary_op(ZEND_MOD, $1, $3); }
Zend/zend_opcode.c:1042:            case ZEND_MOD:
Zend/zend_opcode.c:1043:                return (binary_op_type) mod_function;
Zend/zend_operators.c:1333:    ZEND_API int ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2) /* {{{ */
Zend/zend_operators.c:1362:        ZVAL_LONG(result, op1_lval % op2_lval);
biziclop at vipmail dot hu 18-Jun-2019 06:18
For positive modulos, here is a mathematically proper modulo which actually works with negative integers.

<?php
// Inline: $v is value to be divided, $m is the modulus
$remainder = ( $v % $m + $m ) % $m;

// Or as a function:
function modulo( $value, $modulus ){
  return (
$value % $modulus + $modulus ) % $modulus;
}

// Test:
for( $x = -6; $x <= 6; ++$x )  echo $x, "\t", modulo( $x, 3 ), "\t<br>\n";
/* prints:
-6  0
-5  1
-4  2
-3  0
-2  1
-1  2
 0  0
 1  1
 2  2
 3  0
*/
?>
philippe 15-Nov-2017 12:06
To get a positiv result

function modulo(int $a, int $b):?int {
  if ($b == 0) {
    throw new Exception('modulo : second operand must not be zero');
  }
  $b = abs($b);
  // test $b == 1 for performance when $a < 0
  return ($b == 1) ? 0 : (($a < 0) ? modulo($a + $b, $b) : $a % $b);
}
peter at icb dot at 07-Jul-2017 10:01
If you need the mathematical modulo (always positive) from negative numbers, use this small function:

<?php
function modulo($a , $b) { return ($a + $b) % $b; }

// examples:
echo modulo(15, 12);  // 3
echo modulo(-9, 12);  // 3
?>
pr dot dot dot dot k at g dot dot dot com 16-Feb-2017 04:57
The modulus operator is very poorly suited for such a simple operation as determining if an int is even or odd. On most common systems, modulus performs a division, which is a very slow operation.
A much better way to find if a number is even or odd is to use the bitwise & operator.

e.g.

$is_odd = $x & 1; //using and
$is_odd = $x % 2; //using modulus
Dominik Buechler 05-Dec-2014 01:01
In addition to Jonathan's comment, there is a way simpler way to determine if an integer is even or not:

<? $odd = $i % 2; ?>
or
<? $even = !($i % 2); ?>

This works because a modulo division by 2 will always return either 0 or the rest 1. Since those are valid boolean values you can just invert them by adding a prefixed ! if wanted.
lmc at trendicy dot com 09-Sep-2014 05:50
If you are running a php version older than 5.6, you can calculate $a ** $b by using exp($b*log($a))
Andrew 17-Jul-2013 02:10
The % operator doesn't behave as many people with a maths background would expect, when dealing with negative numbers. For example, -1 mod 8 = 7, but in PHP, -1 % 8 = -1.

The following function has the expected behaviour:

function mod($a, $n) {
    return ($a % $n) + ($a < 0 ? $n : 0);
}

mod(-1, 8) returns 7 as expected.
php at richardneill dot org 18-Apr-2011 08:13
For larger numbers (above PHP_INT_MAX), use fmod() rather than %.
The other operators (+-*/) work correctly with floats and integer overflow, but % uses integer wrap. Eg.

<?php
var_dump
(0xffffffff % 2);
//Prints  int(-1)   which is WRONG

var_dump(intval(fmod(0xffffffff,2)));
//Prints int(1)   which is the right answer
?>

(The reason this matters is that PHP's float is actually a double, and can accurately represent integers up to 52-bits, even on 32-bit systems)
TheWanderer 05-Jun-2008 03:52
It is worth noticing that when working with large numbers, most noticably using the modulo operator, the results depend on your CPU architecture. Therefore, running a decent 64-bit machine will be to your advantage in case you have to perform complex mathematical operations. Here is some example code - you can compare its output on x86 and x86_64 machines:
<?php
/* tested under PHP 5.2.6-1 with Suhosin-Patch 0.9.6.2 (cli) on both i386 and amd64, Debian lenny/sid */
$a = 2863311530;
$b = 256;
$c = $a % $b;
echo
"$c <br />\n";
echo (
2863311530 % 256)." <br />\n"; /* directly with no variables, just to be sure */
?>

The code is expected to produce '170' if working correctly (try it in spreadsheet software).
calmarius at atw dot hu 15-May-2008 06:19
Be careful when using % with large numbers.

The code:

<?php
   
echo 3333333333 % 3
?>

puts out -1 instead of zero!

(Due to the overflow)
Jonathon Reinhart 16-Oct-2006 02: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>";}
   }
?>
glenn at benge dot co dot nz 05-Oct-2004 11: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 08-Sep-2004 09: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.
info at sima-pc dot com 01-May-2004 02: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.