算术运算符
还记得学校里学到的基本数学知识吗?就和它们一样。
例子 | 名称 | 结果 |
---|---|---|
-$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$ato the$b'th power. Introduced in PHP 5.6. |
除法运算符总是返回浮点数。只有在下列情况例外:两个操作数都是整数(或字符串转换成的整数)并且正好能整除,这时它返回一个整数。
取模运算符的操作数在运算之前都会转换成整数(除去小数部分)。
取模运算符%的结果和被除数的符号(正负号)相同。即$a %$b的结果和$a的符号相同。例如:
<?php echo (5 % 3)."\n"; // prints 2 echo (5 % -3)."\n"; // prints 2 echo (-5 % 3)."\n"; // prints -2 echo (-5 % -3)."\n"; // prints -2 ?>
参见手册中的数学函数。
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
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>";} } ?>
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 */ ?>
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.
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);
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); }
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.
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.
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).
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.
If you are running a php version older than 5.6, you can calculate $a ** $b by using exp($b*log($a))
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 ?>
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.
Be careful when using % with large numbers. The code: <?php echo 3333333333 % 3 ?> puts out -1 instead of zero! (Due to the overflow)
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)