Heya,
I was quite surprised that a conversion from NAN
or INF
does not trigger an E_WARNING. Following some examples:
An example:
$f = NAN;
var_dump(++$f); // float NAN
var_dump((float) NAN); // float NAN
var_dump((int) NAN); // int -2147483648 -> what?
var_dump((bool) NAN); // bool true -> makes sense
$f = INF;
var_dump(++$f); // float INF
var_dump((float) INF); // float INF
var_dump((int) INF); // int 0 -> what?
var_dump((bool) INF); // bool true -> so why int 0?
var_dump((int) (bool) INF); // int 1
Another behaviour which I find strange is that a division by 0 yields false and not NAN:
var_dump(1.5/0) ; // boolean false
I am aware of that introducing an E_WARNING
would be somewhat a BC break but I still suggest to consider it because I
rather see it as a bug. Consider the following example:
$f = INF; //somehow INF
was assigned to $f at some point
$g = $f - 1; //$g is still INF
-> correct IMO
$h = (int) $g; // $i = 0; -> the value as such is ok IMO but it should trigger an E_WARNING
$i = $h - 1; //$i = -1 -> especially hard to detect if one does further calculations with such a value
Thoughts on this?
Cheers,
Robert
Another behaviour which I find strange is that a division by 0 yields false and not NAN:
var_dump(1.5/0) ; // boolean falseI am aware of that introducing an
E_WARNING
would be somewhat a BC break but I still suggest to consider it because I
rather see it as a bug. Consider the following example:
$f = INF; //somehowINF
was assigned to $f at some point
$g = $f - 1; //$g is stillINF
-> correct IMO
$h = (int) $g; // $i = 0; -> the value as such is ok IMO but it should trigger anE_WARNING
$i = $h - 1; //$i = -1 -> especially hard to detect if one does further calculations with such a value
Are you testing on Windows? Things are a little odd there with its
32-bit ints on a 64-bit OS. There is a lot of work going on right now to
clean up the Windows situation. (int)INF is not 0 on 64-bit Linux.
INF/NAN convert to 0x8000000000000000 if you force a cast which is why
when you cast it to bool you get true.
The reason for 0x8000000000000000 is not a PHP thing but an x86-64
convention. This value is the indefinite integer value and basically
just tells you that you performed an action that is not defined. And
given that it is not defined, you cannot rely on the behaviour which
might be why on your platform you are getting zero. Although the
subsequent casts you show indicate it isn't actually zero.
I don't see anything incorrect here, but I agree we probably could add
an E_WARNING
to some of these edge cases in addition to the one we have
for division by zero.
-Rasmus
-----Original Message-----
From: Rasmus Lerdorf [mailto:rasmus@lerdorf.com]
Sent: Thursday, January 02, 2014 7:54 PM
To: Robert Stoll; internals@lists.php.net
Subject: Re: [PHP-DEV]NAN
andINF
cast to intAnother behaviour which I find strange is that a division by 0 yields false and not NAN:
var_dump(1.5/0) ; // boolean falseI am aware of that introducing an
E_WARNING
would be somewhat a BC break but I still suggest to consider it because
I
rather see it as a bug. Consider the following example:
$f = INF; //somehowINF
was assigned to $f at some point
$g = $f - 1; //$g is stillINF
-> correct IMO
$h = (int) $g; // $i = 0; -> the value as such is ok IMO but it should trigger anE_WARNING
$i = $h - 1; //$i = -1 -> especially hard to detect if one does further calculations with such a valueAre you testing on Windows? Things are a little odd there with its
32-bit ints on a 64-bit OS. There is a lot of work going on right now to
clean up the Windows situation. (int)INF is not 0 on 64-bit Linux.
INF/NAN convert to 0x8000000000000000 if you force a cast which is why
when you cast it to bool you get true.The reason for 0x8000000000000000 is not a PHP thing but an x86-64
convention. This value is the indefinite integer value and basically
just tells you that you performed an action that is not defined. And
given that it is not defined, you cannot rely on the behaviour which
might be why on your platform you are getting zero. Although the
subsequent casts you show indicate it isn't actually zero.I don't see anything incorrect here, but I agree we probably could add
anE_WARNING
to some of these edge cases in addition to the one we have
for division by zero.-Rasmus
I am testing on Windows 7 64bit.
I was not surprised about the result of the int conversion because it is erroneous conversion anyway, so one cannot rely
on the value. The only thing which surprised me was that no E_WARNING
was triggered.
And the other part about division by 0 yields false. I rethought it and conclude that it makes somewhat sense for a
purely int division. However, it does not make sense for a floating point number division IMO and should be NAN
or INF
instead as suggested by IEEE 754.
Yet, since this would be a BC break I understand that it cannot be changed in 5.x but maybe in PHP 6?
And the other part about division by 0 yields false. I rethought it and conclude that it makes somewhat sense for a
purely int division. However, it does not make sense for a floating point number division IMO and should beNAN
orINF
instead as suggested by IEEE 754.
Yet, since this would be a BC break I understand that it cannot be changed in 5.x but maybe in PHP 6?
Hey, why not make div-by-0 with ints also yield Infinity? It's a nicer
and more practical approach than throwing a warning, IMO, because you
don't have to check for zero at every single division, you'll just get
an eventual output which tells you something went wrong.
--
Andrea Faulds
http://ajf.me/
And the other part about division by 0 yields false. I rethought it and
conclude that it makes somewhat sense for a
purely int division. However, it does not make sense for a floating point
number division IMO and should beNAN
orINF
instead as suggested by IEEE 754.
Yet, since this would be a BC break I understand that it cannot be changed
in 5.x but maybe in PHP 6?Hey, why not make div-by-0 with ints also yield Infinity? It's a nicer and
more practical approach than throwing a warning, IMO, because you don't have
to check for zero at every single division, you'll just get an eventual
output which tells you something went wrong.
I'm +1 to make div by zero return INF.
I'm also +1 for every math "strange" operation to issue a warning,
like div by zero, or else.
Julien
Julien Pauli wrote:
I'm +1 to make div by zero return INF.
This begs the question 'how' ...
If we are processing to integer values they produce an integer result and there
is no provision for a 'number' INF. This is the exact sort of request that
prompted my recent article on 'what is a number' ...
The bottom line is that 'int' simply does not have any means of returning NAN
or
INF
so why are you even discussing it? It is messages relating to an 'int'
object that need handling? Divide when divisor is '0' is a state that needs
handling by the code, what ever the type of number object.
As Rasmus has indicated, how a platform handles these edge cases is the
inconsistent bit that needs documenting, and this is another aspect I need to
add to my notes ...
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
-----Original Message-----
From: Lester Caine [mailto:lester@lsces.co.uk]
Sent: Monday, January 06, 2014 3:16 PM
To: PHP internals
Subject: Re: [PHP-DEV]NAN
andINF
cast to intJulien Pauli wrote:
I'm +1 to make div by zero return INF.
This begs the question 'how' ...
If we are processing to integer values they produce an integer result and there
is no provision for a 'number' INF. This is the exact sort of request that
prompted my recent article on 'what is a number' ...
PHP behaves already different. 1/2 = 0.5
So it would be perfectly valid to define 2/0 = INF
Personally, I would prefer to keep false for a division with two integers (e.g. 1/0) but would change the result as
follows if a float is involved
1.0/0 = INF
1/0.0 = INF
0.0/0 = NAN
0/0.0 = NAN
pretty much as other language behave (right?).
The bottom line is that 'int' simply does not have any means of returning
NAN
or
INF
so why are you even discussing it? It is messages relating to an 'int'
object that need handling? Divide when divisor is '0' is a state that needs
handling by the code, what ever the type of number object.As Rasmus has indicated, how a platform handles these edge cases is the
inconsistent bit that needs documenting, and this is another aspect I need to
add to my notes ...--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Robert Stoll wrote:
I'm +1 to make div by zero return INF.
This begs the question 'how' ...
If we are processing to integer values they produce an integer result and there
is no provision for a 'number' INF. This is the exact sort of request that
prompted my recent article on 'what is a number' ...PHP behaves already different. 1/2 = 0.5
So it would be perfectly valid to define 2/0 =INF
Personally, I would prefer to keep false for a division with two integers (e.g. 1/0) but would change the result as
follows if a float is involved
1.0/0 =INF
1/0.0 =INF
0.0/0 =NAN
0/0.0 =NAN
pretty much as other language behave (right?).
But that is not 'cast to int' ...
http://phpsurgery.org/wiki/integer is my take on some of this, and if you follow
the results on stackoverflow asking why there is not a NAN
or INF
value for
numbers in other languages you will see that your list only works for 'float'
... but mapping everything to float is wrong?
The real problem here is what 'container' is created when calculating
int(x) / int(y) = ???
27/3 can give a clean int(9), but 27/2 has a remainder and 27/0 can't produce an
int() result? Some other container needs to be created?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
But that is not 'cast to int' ...
http://phpsurgery.org/wiki/integer is my take on some of this, and if
you follow the results on stackoverflow asking why there is not aNAN
or
INF
value for numbers in other languages you will see that your list
only works for 'float' ... but mapping everything to float is wrong?The real problem here is what 'container' is created when calculating
int(x) / int(y) = ???
27/3 can give a clean int(9), but 27/2 has a remainder and 27/0 can't
produce an int() result? Some other container needs to be created?
It'd be float in both cases, and I see nothing wrong with implicit float
conversion when using int to represent isn't possible any more.
But if we must, I suppose we might be able to make an "integer" INF
value, though I expect that'd require too much effort to be worth it.
Also, having special-value integers wouldn't be nice. When something's
of a float type, you know it might be special. With ints, you know it
can never be. So I see nothing wrong with float(inf) here.
--
Andrea Faulds
http://ajf.me/
-----Original Message-----
From: Lester Caine [mailto:lester@lsces.co.uk]
Sent: Monday, January 06, 2014 4:22 PM
To: internals@lists.php.net >> PHP internals
Subject: Re: [PHP-DEV]NAN
andINF
cast to intRobert Stoll wrote:
I'm +1 to make div by zero return INF.
This begs the question 'how' ...
If we are processing to integer values they produce an integer result and there
is no provision for a 'number' INF. This is the exact sort of request that
prompted my recent article on 'what is a number' ...PHP behaves already different. 1/2 = 0.5
So it would be perfectly valid to define 2/0 =INF
Personally, I would prefer to keep false for a division with two integers (e.g. 1/0) but would change the result as
follows if a float is involved
1.0/0 =INF
1/0.0 =INF
0.0/0 =NAN
0/0.0 =NAN
pretty much as other language behave (right?).But that is not 'cast to int' ...
That's right, this point of my email was already a bit off topic if you like but anyway, I just wanted to point out that
your reasoning: int / int = int does not hold for PHP in all cases -> 1/2 = 0.5 => int / int = float
And besides, I never suggested that a cast to int should yield NAN
or INF. The main point of my email was that I was
surprised that no E_WARNING
was triggered during the conversion from NAN
to int or INF
to int.
http://phpsurgery.org/wiki/integer is my take on some of this, and if you follow
the results on stackoverflow asking why there is not aNAN
orINF
value for
numbers in other languages you will see that your list only works for 'float'
That's half true, NAN
and INF
are not supported by int but very well by floating point numbers as defined by IEEE 754.
My point was that if the division includes a floating point number (as it is the case in my list above) and thus the
result is a floating point number anyway then it should remain a floating point number. PHP behaves like this in most
cases (the only exception I know is division by 0). Try 27.0/3 and you will see that the result is 9.0 (and not int 9).
That's how other programming languages behave as well - C included. And in the case where a division by 0 occurs (with a
floating point number involved) it should either be NAN
or INF
(according to my list) and not false in my opinion. I
barely do something in C, so don't take the following for granted but I think C also yields INF
or NAN
if a division by
0 occurs and a floating point number was involved.
... but mapping everything to float is wrong?
Sorry, I am not sure how I shall interpret this question, is it ironic/sarcastic? (quite hard to tell in an email mate
^^)
I said, it is perfectly fine to map a division with two int to a float in PHP (since it is already done this way => 1/2
= 0.5). But mapping every division to float would probably mean an unnecessary cast to float sometimes (on the other
hand it would be consistent). I do not think it would be clever to yield always a float in favour of performance.
That said, it would maybe be a good idea to introduce a function int_division($dividend, $divisor) which expects two int
(or cast both variables to int) and yields an int (can use the C integer division). This would certainly be a more
efficient way than using the following code snippet (which one could use right now) - which has quite an overhead for
something so simple as an integer division:
function int_division($dividend, $divisor){
$result = $dividend/$divisor;
if(!is_int($results)){
$result = (int) $result;
}
return $result;
}
The real problem here is what 'container' is created when calculating
int(x) / int(y) = ???
27/3 can give a clean int(9), but 27/2 has a remainder and 27/0 can't produce an
int() result? Some other container needs to be created?
That's why I adjusted my statement and said it is ok to yield false for int/0
I don't know how the source code for a division looks like in PHP, so I would just take a wild guess if I write more
about the actual container.
--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Hi Robert,
-----Original Message-----
From: Rasmus Lerdorf [mailto:rasmus@lerdorf.com]
Sent: Thursday, January 02, 2014 7:54 PM
To: Robert Stoll; internals@lists.php.net
Subject: Re: [PHP-DEV]NAN
andINF
cast to intAnother behaviour which I find strange is that a division by 0 yields
false and not NAN: var_dump(1.5/0) ; // boolean falseI am aware of that introducing an
E_WARNING
would be somewhat a BC
break but I still suggest to consider it because
Irather see it as a bug. Consider the following example: $f = INF;
//somehowINF
was assigned to $f at some point
$g = $f - 1; //$g is stillINF
-> correct IMO
$h = (int) $g; // $i = 0; -> the value as such is ok IMO but it should
trigger anE_WARNING
$i = $h - 1; //$i = -1 -> especially hard to
detect if one does further calculations with such a valueAre you testing on Windows? Things are a little odd there with its
32-bit ints on a 64-bit OS. There is a lot of work going on right now to
clean up the Windows situation. (int)INF is not 0 on 64-bit Linux.
INF/NAN convert to 0x8000000000000000 if you force a cast which is why
when you cast it to bool you get true.The reason for 0x8000000000000000 is not a PHP thing but an x86-64
convention. This value is the indefinite integer value and basically just
tells you that you performed an action that is not defined. And given
that it is not defined, you cannot rely on the behaviour which might be
why on your platform you are getting zero. Although the subsequent casts
you show indicate it isn't actually zero.I don't see anything incorrect here, but I agree we probably could add
anE_WARNING
to some of these edge cases in addition to the one we have
for division by zero.-Rasmus
I am testing on Windows 7 64bit.
I was not surprised about the result of the int conversion because it is
erroneous conversion anyway, so one cannot rely on the value. The only
thing which surprised me was that noE_WARNING
was triggered.And the other part about division by 0 yields false. I rethought it and
conclude that it makes somewhat sense for a purely int division. However,
it does not make sense for a floating point number division IMO and
should beNAN
orINF
instead as suggested by IEEE 754. Yet, since this
would be a BC break I understand that it cannot be changed in 5.x but
maybe in PHP 6?
you might be interested on the int64 branch builds. Please fetch the
latest from here
http://windows.php.net/downloads/snaps/str_size_and_int64/r8260644/ . The
behavior of the INF/NAN case in that branch is identical to that on 64 bit
Linux. Also, you'll probably find one ore another astonishment regarding
win64 in there. I'd really appreciate your feedback.
Thanks
Anatol
Hi Robert,
An example:
$f = NAN;
var_dump(++$f); // floatNAN
var_dump((float) NAN); // floatNAN
var_dump((int) NAN); // int -2147483648 -> what?
var_dump((bool) NAN); // bool true -> makes sense$f = INF;
var_dump(++$f); // floatINF
var_dump((float) INF); // floatINF
var_dump((int) INF); // int 0 -> what?
var_dump((bool) INF); // bool true -> so why int 0?
var_dump((int) (bool) INF); // int 1
I've added this to the RFC as an issue.
https://wiki.php.net/rfc/comparison_inconsistency
BTW, this issue could be mitigated by GMP float support.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
I've added this to the RFC as an issue.
https://wiki.php.net/rfc/comparison_inconsistency
The introduction on that RFC links to a rather confused bug report about
min()
and max()
behaviour with mixed types. [1] The actual behaviour for
comparisons between types is documented on the manual page for
Comparison Operators [2], and is a largely separate issue to the
behaviour of the actual conversions - it is not a question of how the
values behave when converted, but which conversions are applied.
The current documentation for min()
and max()
is thoroughly unhelpful,
implying special cases which don't exist, and missing behaviours that
do. I submitted a patch on edit.php.net with revised examples and a
clearer explanation and link to that page, but there seems to have been
a glitch somewhere: the patches showed in the "Contributions are ready"
reports for a while [3] but then seemingly disappeared without trace - I
asked if anyone knew where they were, but nobody answered [4].
The non-commutativity of conversions does make this all very confusing
(sorting arrays containing mixed types is actually unpredictable in some
cases, and again the documentation is rather lacking), but is inevitable
since such conversions may be "lossy" - e.g. (bool)42, (bool)43, and
(bool)44 cannot possibly be distinct values. The only other option in
many cases is simply to throw an error when such a comparison is
attempted, and reject the entire computation.
Links:
[1] https://bugs.php.net/bug.php?id=53104
[2] http://php.net/manual/en/language.operators.comparison.php
[3] http://news.php.net/php.doc/969384748
[4] http://news.php.net/php.doc/969384775
Regards,
--
Rowan Collins
[IMSoP]