Bug #78073 [Nab]: echo fmod(25, 0.2); // 0.2, must be 0
| From: | e dot grinec at gmail dot com | Date: | Mon, 27 May 2019 10:43:16 +0000 |
| Subject: | Bug #78073 [Nab]: echo fmod(25, 0.2); // 0.2, must be 0 | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-221005@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78073&edit=1
ID: 78073
User updated by: e dot grinec at gmail dot com
Reported by: e dot grinec at gmail dot com
Summary: echo fmod(25, 0.2); // 0.2, must be 0
Status: Not a bug
Type: Bug
Package: *Math Functions
Operating System: Windows 10 x64
PHP Version: 7.3.5
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
function fmod($x, $y) {
if (!$y) { return NAN; }
$q = $x / $y;
$f = ($q < 0 ? 'ceil' : 'floor');
return $x - $f($q) * $y;
}
Previous Comments:
------------------------------------------------------------------------
[2019-05-27 10:39:39] cmb@php.net
Floating point values have a limited precision. Hence a value might
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly
printing it without any mathematical operations.
If you would like to know more about "floats" and what IEEE
754 is, read this:
http://www.floating-point-gui.de/
Thank you for your interest in PHP.
The magnitude of the result is smaller than the divisor, see
<https://3v4l.org/ZlnYS>.
------------------------------------------------------------------------
[2019-05-27 09:58:56] e dot grinec at gmail dot com
The following patch has been added/updated:
Patch Name: patch.txt
Revision: 1558951136
URL: https://bugs.php.net/patch-display.php?bug=78073&patch=patch.txt&revision=1558951136
------------------------------------------------------------------------
[2019-05-27 09:51:43] e dot grinec at gmail dot com
Description:
------------
---
From manual page: https://php.net/function.fmod
---
PHP 5.2.x through PHP 7.3.2 still the same problem.
Code:
<?php
echo fmod(-25, 0.2); // -0.2, should be 0
echo -25 - floor(-25/0.2) * 0.2; // 0, as it should be
?>
Default installation of OSPanel (OpenServer 5.2.2) with default configuration of php.ini and etc in
it.
Documentation says:
"Returns the floating point remainder of dividing the dividend (x) by the divisor (y). The
remainder (r) is defined as: x = i * y + r, for some integer i. If y is non-zero, r has the same
sign as x and a magnitude LESS than the magnitude of y."
But r magnitude EQUAL to y.
Solution:
function fmod($x, $y){return echo $x - floor($x/$y) * $y;}
Test script:
---------------
<?php
echo var_dump(fmod(21, 0.2) == 0); // bool(false)
echo var_dump(fmod(1, 0.1) == 0); // bool(false)
echo fmod(1, 0.1); // 0.1
echo fmod(1, 0.2); // 0.2
Expected result:
----------------
<?php
echo var_dump(fmod(21, 0.2) == 0); // bool(true)
echo var_dump(fmod(1, 0.1) == 0); // bool(true)
echo fmod(1, 0.1); // 0
echo fmod(1, 0.2); // 0
Actual result:
--------------
bool(false)
bool(false)
0.1
0.2
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78073&edit=1