Hi internals,
I would like to present the RFC to add the
"is_representable_as_float()" and "is_representable_as_int()"
functions. These functions provide developers with a way to check
whether values can be losslessly converted between integer and
floating-point representations.
https://wiki.php.net/rfc/is-representable-as-float-int
Best,
Alexandre Daubois
Hi internals,
I would like to present the RFC to add the
"is_representable_as_float()" and "is_representable_as_int()"
functions. These functions provide developers with a way to check
whether values can be losslessly converted between integer and
floating-point representations.https://wiki.php.net/rfc/is-representable-as-float-int
Best,
Alexandre Daubois
This looks lovely.
Since only int, float, and string can ever be true, does it make sense to type the function parameters as int|float|string
rather than mixed
, to automatically exclude arrays, objects, and null? (All of which would always be false.)
(I could probably argue either way on it, but my first inclination is yes; push the initial validation upstream. You should always know if a variable is a primitive or not, at the very least.)
--Larry Garfield
Hi internals,
I would like to present the RFC to add the
"is_representable_as_float()" and "is_representable_as_int()"
functions. These functions provide developers with a way to check
whether values can be losslessly converted between integer and
floating-point representations.https://wiki.php.net/rfc/is-representable-as-float-int
Best,
Alexandre DauboisThis looks lovely.
Since only int, float, and string can ever be true, does it make sense
to type the function parameters asint|float|string
rather thanmixed
,
to automatically exclude arrays, objects, and null? (All of which would
always be false.)
There is prior art and also I'd personally recommend to abide to mixed to
not open new gaps while closing older.
php --rf is_countable
Function [ <internal:standard> function is_countable ] {
- Parameters [1] {
Parameter #0 [ <required> mixed $value ]
}
- Return [ bool ]
}
(I could probably argue either way on it, but my first inclination is
yes; push the initial validation upstream. You should always know if a
variable is a primitive or not, at the very least.)
IMHO this is not a validation but a test function.
So if you think one should know, you probably should not need this function
at all.
Btw. is_primitive() was not a thing last time I looked. It would be great
though to have the combined test of is_scalar()
and is_null()
in a single
function call.
This is perhaps something for the line-up.
Just my 2 cents
-- hakre
So if you think one should know, you probably should not need this function
at all.
That's right. I'd also say that since the aim is to have better
interoperability between systems, mixed seems judicious. For example,
a bool or a null can occur.
Btw. is_primitive() was not a thing last time I looked. It would be great
though to have the combined test ofis_scalar()
andis_null()
in a single
function call.
I like the idea. Would it have its place in this RFC? I feel like it
could with a separate vote, but maybe this would require its own RFC.
Btw. is_primitive() was not a thing last time I looked. It would be
great
though to have the combined test ofis_scalar()
andis_null()
in a
single
function call.I like the idea.
Thanks.
Would it have its place in this RFC? I feel like it
could with a separate vote, but maybe this would require its own RFC.
Nah, at least me would not put it in there. But maybe after that RFC is
done, we probably should revisit the idea.
With representable as float, is_primitive() could get even more clarity
apart from the ordinary type test, and probably buy into the commons
mirrored in the rel. recent JSON Path Internet-RFC JSON value mindset,
which was with an early PHP implementation since it's beginning ca. 20
years or so ago. If we're able to capture such longtime wisdom within the
language it would be a testament to software engineering in web/phptech and
could become a beautiful example of unveiling true ergonomics.
My 2 cents
-- hakre
Alexandre Daubois alex.daubois+php@gmail.com hat am 29.07.2025 14:52 CEST geschrieben:
Hi internals,
I would like to present the RFC to add the
"is_representable_as_float()" and "is_representable_as_int()"
functions. These functions provide developers with a way to check
whether values can be losslessly converted between integer and
floating-point representations.https://wiki.php.net/rfc/is-representable-as-float-int
Best,
Alexandre Daubois
Thanks for the RFC.
Since frameworks already have things like Strings::is_stringable() and Arr::arrayable(), I'd suggest to use is_floatable(), is_intable() or is_integerable(), etc.
To me, this would also feel more consistent is is_float()
, is_int()
, etc.
Regards
Thomas
Since frameworks already have things like Strings::is_stringable() and Arr::arrayable(), I'd suggest to use is_floatable(), is_intable() or is_integerable(), etc.
To me, this would also feel more consistent isis_float()
,is_int()
, etc.
I get what you mean. Naming is definitely challenging here. However,
with alternatives like "is_floatable()", I'm afraid that it is not
clear enough that there's a potential loss of precision. I would
personally feel that "is_floatable()" would mean "can this be cast to
float?" without further "limitation".
Best,
Alexandre Daubois
In general, I think the proposed semantics make sense. I'm not sure
about the names, but it's hard to think of a name that accurately
describes what they do.
The value is a float that is not NaN or infinity
It feels a bit odd to have a value where is_float($v) would be true, but
is_representable_as_float($v) would be false. I'd be interested to
understand the thinking behind this case.
Because of this, the function return value is also platform-dependent:
is_representable_as_float(PHP_INT_MAX); // true on 64-bit platforms, false on 32-bit platforms
This is, at best, misleading: it's not the function that's behaving
differently, it's just being given different input. By that reasoning,
strlen()
is platform-dependent, because strlen(PHP_OS_FAMILY) returns 5
on Linux but 7 on Windows.
As written, it's also the wrong way around: on a 32-bit platform, you
are passing 2147483647, which is a "safe" value; on a 64-bit platform,
you are passing 9223372036854775807, which is an odd number outside the
"safe" range.
is_representable_as_float(2147483647) === true on any platform
is_representable_as_float(9223372036854775807) === false on a 64-bit build
Confusingly, passing that absolute value on a 32-bit system will appear
to return true, but that's because the loss of precision has already
happened in the compiler: 9223372036854775807 will actually be compiled
as 9223372036854775808.0, the nearest representable float. So again,
it's actually running the same function with different input, not
different behaviour inside the function.
I suggest removing that sentence and example completely. There is
nothing the function can or should do differently on different platforms.
Here also, the function return value is platform-dependent:
is_representable_as_int(2**31); // true on 64-bit platforms, false on 32-bit platforms
This one is fair enough, but I'd suggest tweaking the example slightly
to avoid the same problem with different inputs: on a 64-bit build,
2**31 already is an integer, so it's trivially true. So either force a
floating point input:
is_representable_as_int(2.0**31); // true on 64-bit platforms, false on
32-bit platforms
or, perhaps clearer, use an out-of-range string input:
is_representable_as_int('2147483648'); // true on 64-bit platforms,
false on 32-bit platforms
Regards,
--
Rowan Tommins
[IMSoP]
The value is a float that is not NaN or infinity
It feels a bit odd to have a value where is_float($v) would be true, but is_representable_as_float($v) would be false. I'd be interested to understand the thinking behind this case.
As the strings “INF” and “NAN” can't be cast as floats directly, I
think it's safer to return false on these extreme values. See
https://3v4l.org/TabMK#vnull for the cast example.
I suggest removing that sentence and example completely. There is nothing the function can or should do differently on different platforms.
You are right, it's misleading. I'll update the RFC accordingly.
This one is fair enough, but I'd suggest tweaking the example slightly to avoid the same problem with different inputs: on a 64-bit build, 2**31 already is an integer, so it's trivially true. So either force a floating point input:
is_representable_as_int(2.0**31); // true on 64-bit platforms, false on 32-bit platforms
or, perhaps clearer, use an out-of-range string input:
is_representable_as_int('2147483648'); // true on 64-bit platforms, false on 32-bit platforms
I'll also update accordingly. Thank you!
Best,
Alexandre Daubois
The value is a float that is not NaN or infinity
It feels a bit odd to have a value where is_float($v) would be true, but is_representable_as_float($v) would be false. I'd be interested to understand the thinking behind this case.
As the strings “INF” and “NAN” can't be cast as floats directly, I
think it's safer to return false on these extreme values. See
https://3v4l.org/TabMK#vnull for the cast example.
The sentence I quoted isn't talking about string inputs, it's talking about values that are already floats. The fact that you can't create one from a string cast doesn't seem relevant, if you have in fact created one some other way.
Rowan Tommins
[IMSoP]
The sentence I quoted isn't talking about string inputs, it's talking about values that are already floats. The fact that you can't create one from a string cast doesn't seem relevant, if you have in fact created one some other way.
Ah yes, my bad. I just updated the RFC page with your previous
comments. Also, I changed examples of INF
and NAN
to return true with
"is_representable_as_float()". The example of the float overflowing to
infinity (2**1024) is also updated to return true.
Best,
Alexandre Daubois
I would like to present the RFC to add the
"is_representable_as_float()" and "is_representable_as_int()"
functions. These functions provide developers with a way to check
whether values can be losslessly converted between integer and
floating-point representations.
The RFC is now updated with the draft implementation of the current
state of the document. The draft PR is available at
https://github.com/php/php-src/pull/19308.
Best,
Alexandre Daubois