Re: Fix division by zero to throw exception (round 2)
| From: | Bob Weinand | Date: | Mon, 29 Jun 2015 17:02:01 +0000 |
| Subject: | Re: Fix division by zero to throw exception (round 2) | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-86945@lists.php.net to get a copy of this message | ||
Hey Andrea,
> Am 29.06.2015 um 18:49 schrieb Andrea Faulds <ajf@ajf.me>:
>
> Hi Bob,
>
>> On 29 Jun 2015, at 16:54, Bob Weinand <bobwei9@hotmail.com> wrote:
>>
>> I would like to bring this topic back up, as there were users confused with it and
>> it's absolutely not consistent what we have now.
>> See also https://bugs.php.net/bug.php?id=69957 (As I
>> thought it was non-intentional, I went ahead and "fixed" it, was reverted later, hence
>> discussing that now here.)
>>
>> So, looks like there was some quick decisions and discussion I totally had missed.
>> What we have now is:
>>
>>> Am 03.04.2015 um 23:13 schrieb Dmitry Stogov <dmitry@zend.com>:
>>>
>>> So the summary:
>>>
>>> 1) division by zero produces a warning and +/-INF IS_DOUBLE. Compile-time
>>> evaluation is disabled.
>>>
>>> 3) Modulo by zero produces Exception.Compile-time evaluation is disabled.
>>
>> Why? Why do we change the one but not the other?
>>
>> Why does 0 % 0 throw an Exception, but 0 / 0 NAN?
>> Why does 1 % 0 throw an Exception, but 1 / 0 INF?
>>
>> I'd like to either properly return 0, INF or NAN in both cases or in none.
>>
>> Having different rules for so similar operations is non-sense, I think. It just is
>> inconsistent and causes confusion.
>
> Those operations are not as similar as you think!
>
> In PHP, the complement of % isn’t /, it’s intdiv(). intdiv() takes an integer divided and
> divisor, and produces an integer quotient. % also takes an integer dividend and divisor, but
> produces an integer remainder. intdiv() and % work with integer-only inputs and always produce
> integer outputs.
>
> /, on the other hand, takes an integer or float dividend and divisor, and produces an integer
> or float fractional result. It might as well work only on floats and always produce floats, really,
> given that it behaves the same as if it did.
>
> So intdiv() and % work on integers, and / works on integers and floats. This informs how they
> handle certain error cases.
>
> For integer division and modulo (PHP’s intdiv() and %), the accepted way to handle division
> by zero is to produce an error. There’s no correct or useful result you can produce. In PHP, we
> used to produce FALSE here, which is a different type (boolean). I don’t think that was a good
> idea because of PHP’s weak typing. If you use FALSE in some other arithmetic operation, it’ll be
> coerced to zero, and produce weird results from other operations. Sure, there’s an E_WARNING
> produced, but your code keeps running and produces garbage. So, throwing an exception is safer and
> brings PHP into line with established practice in other programming languages.
>
> For floating-point division (PHP’s /), on the other hand, errors are usually handled
> differently. IEEE 754 defines special error values we can produce: +Infinity, -Infinity and NaN.
> These are still values of the float type, but they’re not normal numbers. They flow through
> floating-point operations in a well-defined manner. For example, if you do anything with a NaN and a
> NaN, you get a NaN, while if you divide by zero, you get ±Infinity, and if you divide by Infinity,
> you get ±0. Again, PHP used to produce FALSE here, which has the problems described earlier.
> ±Infinity and NaN, on the other hand, flow properly through later arithmetic operations. If the
> error affects your result, it will most likely be obvious, because it’ll be ±0, ±Infinity, or
> NaN. Yes, you result is garbage, but it’s at least obviously so. And, like with the integer
> behaviour, this brings PHP into line with established practice.
>
> tl;dr: intdiv() and % have matching behaviour because they work with integers and that’s
> what’s usually does for them, / has different behaviour because it works with floats and that’s
> what’s done for them.
>
> I hope that makes sense.
>
> --
> Andrea Faulds
> http://ajf.me/
> <http://ajf.me/>
Yes, it generally makes sense...
Then I have other questions:
- Why do we then still have a Warning? Either we have well-defined behavior, or we throw an
exception. Well-defined behavior *plus* a warning is IMO non-sense.
- Is it intentional for intdiv and % to throw an Exception instead of Error or some more specific
DivisionByZeroError or similar? (yes, I know, Error is only very recent, but the question still
needs to be asked).
Bob.