GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Downloads
  • Documentation
  • Get Involved
  • Help
  • Getting Started
  • Introduction
  • A simple tutorial
  • Language Reference
  • Basic syntax
  • Types
  • Variables
  • Constants
  • Expressions
  • Operators

This view

  • Original page
  • New address

GeezerVison is showing www.php.net — PHP: fmod - Manual

PHP 8.6.0 RC5 available for testing
    fpow »
    « floor
    • Preface
    • Function Reference
    • Mathematical Extensions
    • Math
    • Math Functions

    fmod

    (PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)

    fmod — Returns the floating point remainder (modulo) of the division of the arguments

    Description

    function fmod(float $num1, float $num2): float

    Returns the floating point remainder of dividing the dividend (num1) by the divisor (num2). The remainder (r) is defined as: num1 = i * num2 + r, for some integer i. If num2 is non-zero, r has the same sign as num1 and a magnitude less than the magnitude of num2.

    Parameters

    num1

    The dividend

    num2

    The divisor

    Return Values

    The floating point remainder of num1/num2. NAN (float) if the second argument is 0.

    Examples

    Example #1 Using fmod()

    <?php
    $x = 5.7;
    $y = 1.3;
    $r = fmod($x, $y);
    // $r equals 0.5, because 4 * 1.3 + 0.5 = 5.7
    
    var_dump($x, $y, $r);
    ?>

    See Also

    • / - Floating-point division
    • % - Integer modulus
    • intdiv() - Integer division - Integer division

    Found A Problem?

    Learn How To Improve This Page • Submit a Pull Request • Report a Bug
    +add a note

    User Contributed Notes 7 notes

    up
    down
    11
    jphansen at uga dot edu ¶
    21 years ago
    fmod() does not mirror a calculator's mod function. For example, fmod(.25, .05) will return .05 instead of 0 due to floor(). Using the aforementioned example, you may get 0 by replacing floor() with round() in a custom fmod().
    
    <?
    function fmod_round($x, $y) {
        $i = round($x / $y);
        return $x - $i * $y;
    }
    
    var_dump(fmod(.25, .05)); // float(0.05)
    var_dump(fmod_round(.25, .05)); // float(0)
    ?>
    up
    down
    3
    nospam at neonit dot de ¶
    9 years ago
    Note that fmod does not behave like a similar function written in PHP itself does due to the lack of fixing floating point representation errors.
    
    Have a look at this:
    <?php
    var_dump(10 / (10 / 3) === 3.0); // bool(true)
    var_dump(fmod(10, 10 / 3)); // float(3.3333333333333)
    var_dump(fmod(10, 10 / 3) < 10 / 3); // bool(true)
    ?>
    
    Internally there is no way of exactly representing the result of 10 / 3, so it will always be a bit above or below the actual result. In this case, the example proves it being a bit above the actual result.
    
    PHP seems quite good at auto-fixing floating point representation errors so they behave like the user would expect it. That's why the first line yields true, although the result is slightly below 3 (like 2.9999999999[something]). I failed to trick PHP into rounding or cropping the result to 2.
    
    However, fmod seems to not apply these fixes during calculations. From 10 / 3 it gets a value slightly below 3, floors it to 2 and returns 10 - 2 * 10 / 3, which is slightly less than the actual result of 10 / 3, but looks like 10 / 3 (third line).
    
    Unfortunately, this is not the expected result. See other notes for high quality fixes.
    up
    down
    2
    dePijd ¶
    16 years ago
    This class ran through several unit tests and fixes all failures found in bugs.php.net
    
    <?php
    abstract class MyNumber {
        public static function isZero($number, $precision = 0.0000000001)
        {
            $precision = abs($precision);
            return -$precision < (float)$number && (float)$number < $precision;
        }
        public static function isEqual($number1, $number2)
        {
            return self::isZero($number1 - $number2);
        }
        public static function fmod($number1, $number2)
        {
            $rest = fmod($number1, $number2);
            if (self::isEqual($rest, $number2)) {
                return 0.0;
            }
            if (mb_strpos($number1, ".") === false) {
                $decimals1 = 0;
            } else {
                $decimals1 = mb_strlen($number1) - mb_strpos($number1, ".") - 1;
            }
            if (mb_strpos($number2, ".") === false) {
                $decimals2 = 0;
            } else {
                $decimals2 = mb_strlen($number2) - mb_strpos($number2, ".") - 1;
            }
            return (float)round($rest, max($decimals1, $decimals2));
        }
    }
    ?>
    up
    down
    3
    cory at lavacube dot net ¶
    20 years ago
    I don't believe that is correct.
    
    Try this out using your patch:
    <?php
    
    echo duration( mktime(0, 0, 0, 1, 0, 2006)-time() );
    
    ?>
    
    As of right now, this will read:
    1 month, 22 days, 24 hours, 49 minutes, 15 seconds
    
    Which is completely incorrect. Seeing as how it is the 9th of December.
    
    The real real flaw here is how the 'year' and 'month' periods are calculated. As most months vary in length...
    
    Thank you very much SnakeEater251 for pointing this out.
    
    The quickest way to get slightly more accurate results, is to use averages based on one "true" year, which is 365.25 days.
    
    Change the year and month to:
          'year'       => 31557600, // one 'true year' (365.25 days)
          'month'    => 2629800, // one 'true year' divided by 12 :-)
    
    I will work on developing a true fix, for pin-point accuracy. ;-)
    
     - Cory Christison
    up
    down
    2
    alex at xelam dot net ¶
    22 years ago
    Integer Modulo
    
    If you want the remainder of the division of two Integers rather than Floats, use "%"; eg:
    
    <?php
    $a = 4;
    $b = 3;
    
    print($a % $b);
    ?>
    
    Will output "1".
    up
    down
    0
    picaune at hotmail dot com ¶
    23 years ago
    NAN (.net Equivalent = Double.NaN) means "Not-a-Number".
    Some ways to get NaN are modulo 0, and square root of 0.
    up
    down
    -1
    dan danschafer net ¶
    8 years ago
    WARNING: Due to how floating point numbers work, fmod() and any simple alternatives are problematic when there is either a massive orders of magnitude different between the input $x and $y, or the input and output values. If you need to work with large numbers or arbitrary precision, it is best to work with something like BC Math or GMP.
    
    When working around fmod()'s problems, remember that floor() always goes towards -INF, not 0. This causes a commonly proposed fmod() alternative to only work with positive numbers:
    <?php 
    function fmod_positive_only($x, $y) {
        return $x - floor($x/$y) * $y;
    }
    ?>
    Given these simplistic input values:
    fmod_positive_only(-5, 3) = 1 (wrong)
    -5 % 3 = -2 (correct)
    
    Correctly removing the decimal part of the quotient can be achieved with either casting to an int (always goes towards zero) or dynamically choosing ceil() or floor(). Dynamically choosing floor or ceil in an attempt to keep precision is overkill. If your $x and $y values are so different that it suffers from an overflow problem when casting, it was probably going to have precision problems anyway (see warnings below).
    
    <?php 
    function fmod_overkill($x, $y) {
        if (!$y) { return NAN; }
        $q = $x / $y;
        $f = ($q < 0 ? 'ceil' : 'floor');
        return $x - $f($q) * $y;
    }
    ?>
    
    This is the "best" alternative for fmod() when given "normal" numbers.
    <?php
    function fmod_alt($x, $y) {
        if (!$y) { return NAN; }
        return floatval($x - intval($x / $y) * $y);
    }
    ?>
    
    WARNING: Even when you get a non-zero response, know your input numbers and when fmod() can go wrong. For large values or depending on your input variable types, float still may not contain enough precision to get back the correct answer. Here are a few problems with fmod() and their alternatives.
    
    PHP_INT_MAX = 9223372036854775807
    fmod(PHP_INT_MAX, 2) = 0 (wrong)
    fmod_alt(PHP_INT_MAX, 2) = 0 (wrong)
    PHP_INT_MAX % 2 = 1 (correct)
    
    fmod(PHP_INT_MAX, PHP_INT_MAX - 1) = 0 (wrong)
    fmod_alt(PHP_INT_MAX, PHP_INT_MAX - 1) = 1 (correct)
    fmod_alt(PHP_INT_MAX, PHP_INT_MAX - 1.0) = 0 (wrong)
    PHP_INT_MAX % (PHP_INT_MAX - 1) = 1 (correct)
    PHP_INT_MAX % (PHP_INT_MAX - 1.0) = 9223372036854775807 (wrong)
    
    fmod(PHP_INT_MAX, 131) =  98 (wrong)
    fmod_alt(PHP_INT_MAX, 131) = 359 (wrong)
    fmod_positive_only(PHP_INT_MAX, 131) = 0 (wrong)
    PHP_INT_MAX % 131 = 97 (correct)
    +add a note
    • Math Functions
      • abs
      • acos
      • acosh
      • asin
      • asinh
      • atan
      • atan2
      • atanh
      • base_​convert
      • bindec
      • ceil
      • clamp
      • cos
      • cosh
      • decbin
      • dechex
      • decoct
      • deg2rad
      • exp
      • expm1
      • fdiv
      • floor
      • fmod
      • fpow
      • hexdec
      • hypot
      • intdiv
      • is_​finite
      • is_​infinite
      • is_​nan
      • log
      • log10
      • log1p
      • max
      • min
      • octdec
      • pi
      • pow
      • rad2deg
      • round
      • sin
      • sinh
      • sqrt
      • tan
      • tanh
    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.