• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 算术运算符

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

    算术运算符
    例子名称结果
    -$a取反$a的负值。
    $a +$b加法$a$b的和。
    $a -$b减法$a$b的差。
    $a *$b乘法$a$b的积。
    $a /$b除法$a除以$b的商。
    $a %$b取模$a除以$b的余数。
    $a **$bExponentiationResult 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)