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
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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)

Add a Patch

Pull Requests

Add a Pull Request

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: Fri Apr 19 16:01:27 2024 UTC