В школе нас учили, что делить на ноль нельзя. Если слишком не углубляться в различные математические абстракции, то можно признать, что деление на ноль недопустимо. Однако как обстоят дела в программировании, где правила немного отличаются?
Большинство современных языков программирования следуют IEEE 754. С вещественными числами всё понятно, там при делении на ноль будет либо +Infinity, либо -Infinity во всех этих языках, кроме случая деления самого вещественного нуля на вещественный ноль, в котором результатом будет NaN (not-a-number). Но существуют языки программирования, где деление с вещественными числами работает иначе. Кто-нибудь знает такие?
JavaScript:
1 2 3 4 5 6 7 8 9 |
var y = 0.0 / 0.0; alert(isNaN(y)); // true var q = 23.0 / 0.0; alert(q); // Infinity var w = -56.3 / 0.0; alert(w); // -Infinity |
Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
~$ jshell | Welcome to JShell -- Version 11.0.11 | For an introduction type: /help intro jshell> double y = 0.0 / 0.0; y ==> NaN jshell> double q = 23.0 / 0.0; q ==> Infinity jshell> double w = -56.3 / 0.0; w ==> -Infinity jshell> |
Для целых чисел арифметика работает немного по-другому. В стандарте IEEE 754 при делении на ноль должна возникать ошибка, что делить на ноль нельзя.
В JavaScript просто нет типа целых чисел, поэтому я не могу там провести эти опыты.
Java же строго следует IEEE 754:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ jshell | Welcome to JShell -- Version 11.0.11 | For an introduction type: /help intro jshell> int y = 0 / 0; | Exception java.lang.ArithmeticException: / by zero | at (#1:1) jshell> int q = 23 / 0; | Exception java.lang.ArithmeticException: / by zero | at (#2:1) jshell> int w = -56 / 0; | Exception java.lang.ArithmeticException: / by zero | at (#3:1) |
C# полностью соответствует IEEE 754, как и Java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System; class HelloWorld { static void Main() { // вещественные числа double y = 0.0 / 0.0; Console.WriteLine("y = " + y); // NaN double q = 23.0 / 0.0; Console.WriteLine("q = " + q); // +Infinity double w = -56.0 / 0.0; Console.WriteLine("w = " + w); // -Infinity // целые числа int a = 0; // Создаем переменную, так как поделить на константу ноль нам не // даст сам компилятор try { int y1 = 0 / a; // System.DivideByZeroException Console.WriteLine("y = " + y1); } catch (Exception e) { Console.WriteLine(e); } try { int q1 = 23 / a; // System.DivideByZeroException Console.WriteLine("q = " + q1); } catch (Exception e) { Console.WriteLine(e); } try { int w1 = -56 / a; // System.DivideByZeroException Console.WriteLine("w = " + w1); } catch (Exception e) { Console.WriteLine(e); } } } |
Для C++ ситуация несколько сложнее. В нём при делении на ноль всегда возникает неопределённое поведение (как для вещественных, так и для целых чисел), так как C++ не обязательно должен работать только на процессорах, реализующих IEEE 754. В зависимости от компилятора, архитектуры, оптимизации и т. д. могут возникать разные результаты.
Python тоже не следует IEEE 754. В нём деление на ноль всегда приводит к ошибке ZeroDivisionError:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
$ python3 Python 3.8.10 (default, Jun 2 2021, 10:49:15) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> y = 0.0 / 0.0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: float division by zero >>> q = 23.0 / 0.0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: float division by zero >>> w = -56.3 / 0.0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: float division by zero >>> y = 0 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> w = -56 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> q = 23 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero >>> |
Как думаете, для чего это сделано в Python?
Получается, что существуют языки, которые следуют IEEE 754, а также существуют языки, которые определяют своё собственное поведение, руководствуясь какими-нибудь своими соображениями.