Bug #81601 [Com]: float - (int) float is sometimes bigger than 1
Edit report at https://bugs.php.net/bug.php?id=81601&edit=1
ID: 81601
Comment by: php at leinertco dot com
Reported by: dktapps at pmmp dot io
Summary: float - (int) float is sometimes bigger than 1
Status: Open
Type: Bug
Package: Math related
Operating System: Linux
PHP Version: 8.0.12
Block user comment: N
Private report: N
New Comment:
Try to pass $newLevel as 3rd argument in setXpAndProgress, so you have its value in your logs. Maybe
this will help :/
Previous Comments:
------------------------------------------------------------------------
[2021-11-09 12:14:31] dktapps at pmmp dot io
I do know of several ways to work around it (fmod(f, 1) being the first thing I thought of), but I
thought this should be investigated anyway.
------------------------------------------------------------------------
[2021-11-09 09:58:53] nikic@php.net
If float is larger than INT_MAX, then float - (int) float can trivially be larger than 1. However,
you seem to be working with numbers that are much smaller than that.
I do wonder why this is not implemented as $float - floor($float) though, that seems like the more
natural way to express it, and should avoid edge cases.
------------------------------------------------------------------------
[2021-11-08 20:02:46] dktapps at pmmp dot io
I should clarify, this is definitely NOT a bug in JIT because I've seen this issue in 7.2, 7.3
and 7.4 historically as well.
I also considered the possibility that -ffast-math may be responsible, but I was unable to reproduce
the problem even with -ffast-math.
All tests were done on x86_64.
------------------------------------------------------------------------
[2021-11-08 19:39:38] dktapps at pmmp dot io
Description:
------------
I've seen this issue recur many times over the last few years, but never figured out exactly
what causes it.
This code: https://github.com/pmmp/PocketMine-MP/blob/3dae87373154ad52ff6c27874f3fd93c9845a8af/src/pocketmine/entity/Human.php#L396
is intended to take a float and split it into its whole-number part (the first argument) and its
fractional part (the second argument).
However, sometimes I see crashes like these show in my telemetry:
Value 1.0323429203787 is outside the range 0 - 1
with a trace like this:
#1 pmsrc/src/pocketmine/entity/Human(396): pocketmine\entity\Human->setXpAndProgress(integer 9,
double 1.0323429203787)
#2 pmsrc/src/pocketmine/entity/Human(409): pocketmine\entity\Human->setCurrentTotalXp(integer
158)
To the best of my understanding, this should be impossible.
For context, passing 158 into setCurrentTotalXp() causes $newLevel to become
float(9.922847983320086), which, when run through the offending code on **my** machine, yields this
result:
(int) $newLevel = int(9)
$newLevel - (int) $newLevel = float(0.9228479833200858)
which looks correct.
I have no idea what causes this problem and have never been able to reproduce it firsthand, but such
issues have appeared so frequently and across several PHP versions that I believe this is a bug in
PHP itself.
Expected result:
----------------
float - (int) float should never be larger than 1.
Actual result:
--------------
float - (int) float is sometimes slightly larger than 1.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81601&edit=1
Thread (10 messages)