Hi internals,
On casting a non numeric value to a float in PHP the result will be
float(0).
In PHP-7.0 an exception was introduced that on casting a string
"/\sNaN\s/i" will result in float(NaN).
Wouldn't it be more logical and expected to return NaN in all cases of
casting a non numeric string to a floating point number?
Thanks
Marc
2016-10-23 12:55 GMT+02:00 Marc Bennewitz dev@mabe.berlin:
Hi internals,
On casting a non numeric value to a float in PHP the result will be
float(0).In PHP-7.0 an exception was introduced that on casting a string
"/\sNaN\s/i" will result in float(NaN).Wouldn't it be more logical and expected to return NaN in all cases of
casting a non numeric string to a floating point number?Thanks
Marc--
+1
Regards, Niklas
Am 23.10.2016 um 13:49 schrieb Niklas Keller:
2016-10-23 12:55 GMT+02:00 Marc Bennewitz <dev@mabe.berlin
mailto:dev@mabe.berlin>:Hi internals, On casting a non numeric value to a float in PHP the result will be float(0). In PHP-7.0 an exception was introduced that on casting a string "/\s*NaN\s*/i" will result in float(NaN). https://3v4l.org/2Xakm Wouldn't it be more logical and expected to return NaN in all cases of casting a non numeric string to a floating point number? Thanks Marc --
+1
I just noticed that the behavior change in PHP-7 has been "fixed"
already by https://bugs.php.net/bug.php?id=73329.
So the old behavior will be presented soon.
But I'm still curious why casting any non numeric string results in the
valid number float(0) where there is a special value in floating point
numbers declared to represent not a number values.
I also did a small research on other languages and found the following:
C strtod returns float(0)
-> but supports converting the strings "INFINITY" or "NAN"
(case-insensitive)
JavaScript returns NaN
Python throws ValueError: could not convert string to float
-> but supports the string +/- "NaN", "Inf", "Infinity"
(case-insensitive)
Perl returns float(0)
-> but supports the string +/- "NaN", "Inf", "Infinity"
(case-insensitive)
So there is a nice mix of how other languages will handle this problem.
In my opinion it still makes much more sense to return NaN in any case a
not numeric string will be casted to float incl. "Inf" and "Infinity".
(If spaces should be ignored or suffixes allowed is another question)
= The beginning of a string must contain at least one number by ignoring
spaces to be casted to a valid floating point number. In any other
situations NaN must be returned because this represents what it is = Not
a Number.
So for me the following example table makes sense:
In -> Out
"" -> NaN
" " -> NaN
"+" -> NaN
"-" -> NaN
"." -> NaN
".5" -> 0.5
"0.5" -> 0.5
" 0.5" -> 0.5
"0" -> 0
" 0" -> 0
"Nan" -> NaN
"Inf" -> NaN
"Info" -> NaN
"foo" -> NaN
".foo" -> NaN
".2foo" -> 0.2
" .2foo" -> 0.2
"foo1" -> NaN
"foo." -> NaN
"foo0.1" -> NaN
Thoughts
Marc
Regards, Niklas
Am 23.10.2016 um 21:13 schrieb Marc Bennewitz:
Am 23.10.2016 um 13:49 schrieb Niklas Keller:
2016-10-23 12:55 GMT+02:00 Marc Bennewitz <dev@mabe.berlin
mailto:dev@mabe.berlin>:Hi internals, On casting a non numeric value to a float in PHP the result will be float(0). In PHP-7.0 an exception was introduced that on casting a string "/\s*NaN\s*/i" will result in float(NaN). https://3v4l.org/2Xakm Wouldn't it be more logical and expected to return NaN in all cases of casting a non numeric string to a floating point number? Thanks Marc --
+1
I just noticed that the behavior change in PHP-7 has been "fixed"
already by https://bugs.php.net/bug.php?id=73329.So the old behavior will be presented soon.
But I'm still curious why casting any non numeric string results in the
valid number float(0) where there is a special value in floating point
numbers declared to represent not a number values.I also did a small research on other languages and found the following:
C strtod returns float(0)
-> but supports converting the strings "INFINITY" or "NAN"
(case-insensitive)JavaScript returns NaN
I forgot to mention that in JavaScript (parseFloat) it is nearly the
behavior I would expect. The only difference is that it allows the
string +/- "Infinity" to be casted to Infinity.
Python throws ValueError: could not convert string to float
-> but supports the string +/- "NaN", "Inf", "Infinity"
(case-insensitive)Perl returns float(0)
-> but supports the string +/- "NaN", "Inf", "Infinity"
(case-insensitive)So there is a nice mix of how other languages will handle this problem.
In my opinion it still makes much more sense to return NaN in any case a
not numeric string will be casted to float incl. "Inf" and "Infinity".
(If spaces should be ignored or suffixes allowed is another question)= The beginning of a string must contain at least one number by ignoring
spaces to be casted to a valid floating point number. In any other
situations NaN must be returned because this represents what it is = Not
a Number.So for me the following example table makes sense:
In -> Out
"" -> NaN
" " -> NaN
"+" -> NaN
"-" -> NaN
"." -> NaN
".5" -> 0.5
"0.5" -> 0.5
" 0.5" -> 0.5
"0" -> 0
" 0" -> 0
"Nan" -> NaN
"Inf" -> NaN
"Info" -> NaN
"foo" -> NaN
".foo" -> NaN
".2foo" -> 0.2
" .2foo" -> 0.2
"foo1" -> NaN
"foo." -> NaN
"foo0.1" -> NaNThoughts
MarcRegards, Niklas
Hi,
Marc Bennewitz wrote:
But I'm still curious why casting any non numeric string results in the
valid number float(0) where there is a special value in floating point
numbers declared to represent not a number values.
Because that's what C's strtod() does, and it's also what (int) does
(because that's what C's strtol()) does.
There'd be an argument for using NaN, sure, but it wouldn't be
consistent with the rest of the language. Generally, PHP assumes that a
string with no leading digits has the number value of zero. This is true
not only in (int) and (float) casts, but also in generic number coercion
operations, like with +, -, *, / and **. To change the behaviour of
(float) here would be to introduce a new inconsistency to PHP. If we go
for NaN everywhere, then we introduce a different problem: (int) should
return an integer, and the generic number coercions prefer giving you an
integer rather than a float if appropriate. Producing a NaN here would
mean you'd now get an int rather than a float, and would cause a
cascading change in operation result types which could lead to
previously working code now throwing lots of E_WARNINGs or TypeErrors
(NaN is not accepted for integer type declarations in weak mode, and all
floats are not accepted for integer type declarations in strict mode).
Thanks.
--
Andrea Faulds
https://ajf.me/
Hi Andrea,
Am 24.10.2016 um 15:40 schrieb Andrea Faulds:
Hi,
Marc Bennewitz wrote:
But I'm still curious why casting any non numeric string results in the
valid number float(0) where there is a special value in floating point
numbers declared to represent not a number values.Because that's what C's strtod() does, and it's also what (int) does
(because that's what C's strtol()) does.There'd be an argument for using NaN, sure, but it wouldn't be
consistent with the rest of the language. Generally, PHP assumes that a
string with no leading digits has the number value of zero. This is true
not only in (int) and (float) casts, but also in generic number coercion
operations, like with +, -, *, / and **. To change the behaviour of
(float) here would be to introduce a new inconsistency to PHP. If we go
for NaN everywhere, then we introduce a different problem: (int) should
return an integer, and the generic number coercions prefer giving you an
integer rather than a float if appropriate. Producing a NaN here would
mean you'd now get an int rather than a float, and would cause a
cascading change in operation result types which could lead to
previously working code now throwing lots of E_WARNINGs or TypeErrors
(NaN is not accepted for integer type declarations in weak mode, and all
floats are not accepted for integer type declarations in strict mode).
Thanks for your explanation.
It's totally true that on casting non numeric string to integer will
result in 0 but that's a different type even if it's also a numeric type.
From my understanding PHP tries to cast from one type to another by
loosing as less information as possible. In this case I see a non
numeric string that gets casted to a float will loose exactly this
information that it's "Not a Number" where it would be possible to keep
this information. On casting this to int there is of course no
possibility to keep it but I don't see where it's inconsistent as it's a
different type used for different use-cases.
Having mathematical operations with non numeric strings should result in
the same behavior as NaN will result in NaN which makes sense and I
don't see where it will throw lots on WARNINGS or TypeErrors as it's
still a float. Since PHP-7.0 there was a WARNING introduced "A
non-numeric value encountered" which is nice but the result is still a
valid float where "Not a Number" would be more logical. That's of course
my personal opinion.
Of course changing this would introduce a BC break and therefore should
be reviewed safely. But the bug #73329 shows that there is not much
attention as it stayed for some versions.
This mail is not an RFC not even a proposal it's just mail to get an
answered why (Thanks again) and to see how others think about.
Thanks.
Thanks
Marc
Hi,
Marc Bennewitz wrote:
It's totally true that on casting non numeric string to integer will
result in 0 but that's a different type even if it's also a numeric type.From my understanding PHP tries to cast from one type to another by
loosing as less information as possible. In this case I see a non
numeric string that gets casted to a float will loose exactly this
information that it's "Not a Number" where it would be possible to keep
this information. On casting this to int there is of course no
possibility to keep it but I don't see where it's inconsistent as it's a
different type used for different use-cases.
(int) and (float) are lossy and have always been so. If you want PHP to
complain when you give it something non-numeric, rather than coerce to
0, there are alternatives.
Having mathematical operations with non numeric strings should result in
the same behavior as NaN will result in NaN which makes sense and I
don't see where it will throw lots on WARNINGS or TypeErrors as it's
still a float.
Because previously it would be an integer. "foo" + "bar" currently gives
an integer 0. Now it would give you a float NaN. That has potential
knock-on effects.
Thanks.
--
Andrea Faulds
https://ajf.me/
Hi Marc,
-----Original Message-----
From: Marc Bennewitz [mailto:dev@mabe.berlin]
Sent: Sunday, October 23, 2016 12:56 PM
To: PHP Internals List internals@lists.php.net
Subject: [PHP-DEV] strtod and NaN vs. zeroHi internals,
On casting a non numeric value to a float in PHP the result will be float(0).
In PHP-7.0 an exception was introduced that on casting a string "/\sNaN\s/i"
will result in float(NaN).
It is a BC breaching bug and was fixed https://bugs.php.net/bug.php?id=73329 . Cast of string to number is always zero, a way to change it would cause another BC breach which IMHO were not worthwhile.
Regards
Anatol