php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78073 echo fmod(25, 0.2); // 0.2, must be 0
Submitted: 2019-05-27 09:51 UTC Modified: 2019-05-27 11:23 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: e dot grinec at gmail dot com Assigned: cmb (profile)
Status: Not a bug Package: *Math Functions
PHP Version: 7.3.5 OS: Windows 10 x64
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: e dot grinec at gmail dot com
New email:
PHP Version: OS:

 

 [2019-05-27 09:51 UTC] 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

Patches

patch.txt (last revision 2019-05-27 09:58 UTC by e dot grinec at gmail dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-05-27 09:58 UTC] 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 10:39 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2019-05-27 10:39 UTC] 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 10:43 UTC] e dot grinec at gmail dot com
function fmod($x, $y) {
	if (!$y) { return NAN; }
	$q = $x / $y;
	$f = ($q < 0 ? 'ceil' : 'floor');
	return $x - $f($q) * $y;
}
 [2019-05-27 10:54 UTC] e dot grinec at gmail dot com
Why do you think, that correct answer on this expression

abs(fmod(1, 0.1)) < abs(0.1);

is true?
 [2019-05-27 11:23 UTC] cmb@php.net
PHP's implementation of fmod() just forwards to C's fmod()[1].  If
you think there is a bug in C's fmod(), please report it to the
respective developers.

Thanks.

[1] <https://github.com/php/php-src/blob/php-7.3.6RC1/ext/standard/math.c#L1284-L1294>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 27 18:01:28 2024 UTC