Как стать автором
Обновить

Комментарии 53

У меня в Chrome 78.0.3904.70
Number.isNaN(0/0) === true
Ну и если предположить, что
Number.isNaN(0/0) === false 
, то чему будет равно 0/0?

Ну, так делить на ноль вроде как нельзя, нет? Или что вас удивляет?

В JS можно, как раз NaN и получается.

Ну, так NaN это нот-э-намбэр, то есть не валидная мат-операция, к примеру. Попробуйте пятерку разделить на "привет", то же самое будет.

Согласен, и Number.isNaN вернёт true для 0/0 (и для 6/«привет»), а в статье написано что вернёт false.

А, ясно. Я не читал примеры, но там, судя по всему, ошибка.

Number.isNaN('0/0') === false
Number.isNaN(0/0) === true
В статье все правильно написано.
Первое — вполне валидная строка (и я тоже не понимаю зачем она там для примера) и она действительно вернет false.
Второе — мат.операция, результат которой NaN
В статье исправили, раньше было с ошибкой — просто 0/0 без кавычек.
Обращу внимание что NaN выйдет только при 0/0.
Если делить любое другое число на 0 то получим Infinity.
И кстати
isNaN(Infinity) === false
Number.isNaN(Infinity) === false
НЛО прилетело и опубликовало эту надпись здесь
… что абсолютно соответствует принятым в матане соглашениям. 0/0 — неопределённость, 1/0 — бесконечность, и они друг другу не равны. Вот если вы попробуете сделать 2/0 — 1/0, тогда снова будет NaN
Интересный у вас матан. По определению «a» делится на «b», если существует такое «с», что a = bc.

Рассмотрим 1 / 0. Тогда нам нужно такое «с», что 1 = 0 * c. Очевидно, его не существует. Результат умножения бесконечности на ноль не определен, потому что бесконечность — не число. Если пользоваться теорией пределов, то можно получить любое значение. Да и даже чисто умозрительно: если 1 / 0 = inf и 2 / 0 = inf, то 1 / 0 = 2 / 0 = inf. Множим на ноль и получаем что inf * 0 = 1 = 2. А если множить на ноль по другому, то получим что inf * 0 = 0 = 0.
Но тогда непонятно почему 1 / 0 = inf, если inf * 0 = 0.

Короче, с бесконечностями можно играться только в пределах.


А вот ноль на ноль делиться. Действительно: 0 = 0 * с. «c» тут может быть любым. Таким образом, хоть 0 на 0 и делиться (согласно определению), но результат этого деления не определен.

С точки зрения математики, бесконечность числом не является. А вот в IEEE 754 — является, судя по всему. Во всяком случае там +inf, -inf и NaN — разные сущности.
Нормальный у меня матан, советский, качественный. У авторов IEEE 754 был такой же. Бесконечность — два особых числа, о их сути можно спорить (зависит от того, какие аксиомы мы выбрали в теории множеств и арифметике, которые обе заведомо неполны по Геделю). Но в любом случае для бесконечностей определены все арифметические операции с обычными числами кроме 0, а также часть операций с 0 и другой бесконечностью.
А вот неопределённость — это не число, not-a-number. Абсолютно любая операция числа с не-числом даёт не-число.
Но в любом случае для бесконечностей определены все арифметические операции с обычными числами кроме 0, а также часть операций с 0 и другой бесконечностью.


Извините, но нет.
1 + inf = inf
2 + inf = inf
Такое возможно только если inf — это ноль. Но это не ноль по определению.

В принципе, из этого уже видно что добавление inf в множество чисел ломает групповую операцию. Т.е. с точки зрения теории групп, бесконечность никак не может входить в множество чисел. Но окей, тут действительно можно спорить о выборе аксиоматики для чисел. Давате зайдем с другой стороны.

То что вы описываете, называется «расширенной числовой прямой»: к обычным числам мы добавляем две неведомых зверюшки-бесконечности. И даже там деление на ноль не приводит к бесконечности:

When dealing with both positive and negative extended real numbers, the expression 1/0 is usually left undefined, because, although it is true that for every real nonzero sequence f that converges to 0, the reciprocal sequence 1/f is eventually contained in every neighborhood of {-inf, +inf} it is not true that the sequence 1/f must itself converge to either -inf or +inf. (wiki)


Короче, проблема в том, что 1 / f не сходится к +бесконечности или -бесконечности. Оно сходится и туда и туда одновременно. Собственно, поэтому в анализе и различают «просто» бесконечность, положительную и отрицательную бесконечности.

В том время как в IEEE 754 деление положительного числа на ноль дает положительную бесконечность, а отрицательного — отрицательную. Хотя, согласно матану, положительную бесконечность можно получить если брать односторонний предел 1 / f когда f стремиться к нулю справа. А если брать обычный предел, то как было написано выше получится «просто» бесконечность. Которой нет ни на расширенной числовой прямой, ни в IEEE 754.

Короче, еще раз: в обычной арифметике на ноль делить можно только сам ноль. На расширенной числовой прямой — тоже. Имеет смысл рассматривать пределы вида 1 / x, когда x->0. Но делить на ноль — все равно нельзя. Зато можно делить на бесконечность, да. И
Вы зачем-то пытаетесь приплести матан, хотя здесь просто арифметика. В ней нет пределов, разрывов производных и прочей зауми, там только числа и 4 операции.
И да, откуда у вас появилось требование единственности нейтрального элемента операции сложения? То, что вы знаете про моноиды, ещё не значит, что всё вокруг обязано быть моноидами.

А если нет никаких пределов и разрывов — то и бесконечностей быть не должно, на нормальной числовой прямой их нет.

на нормальной числовой прямой их нет

Почему нет? Вы лично проверяли?:) В некоторых аксиоматиках нет, в других есть. Первые используются в школьных учебниках, вторые — на практике.
Ну так просто в арифметике нет вообще никаких бесконечностей. Им там просто неоткуда взяться. И результат деления на 0 либо не существует (если делим не-ноль), либо — не определен (если делим ноль).

И да, откуда у вас появилось требование единственности нейтрального элемента операции сложения?

Вообще -то я не говорил про требование единственности нейтрального элемента. Тем более, что бесконечность им не является: а + (-а) = 0, а не inf.

Я сказал что добавление бесконечности ломает групповую операцию. Потому что inf + -inf не определено, например.

Вообще, если вы не хотите приплетать матан, то тогда вообще непонятно зачем добавлять бесконечности. Пользы то от этого никакой не будет. Ну да, можно будет сказать a / 0 = inf. А дальше что? Профит в чем? Проблемы вижу: придется в каждую теорему теории чисел добавлять фразу наподобие «кроме случаев, когда n = inf». Попробуйте докажите основную теорему арифметики, если у вас могут быть бесконечности…
Вы ищете теоретический смысл, а он тут сугубо практический.
Обычная машинная арифметика — это арифметика остатков по модулю 2N. Она не очень-то подходит для обычных вычислений из-за переполнений. Скажем, складывая на 8-битном процессоре 100+100, вы получите результат -56. Мало того, что он некорректен, он выглядит нормально. Если такое произойдёт в процессе вычисления какой-то длинной формулы, вы никак не сможете понять, что результат расчёта неверен. И дальше эта ошибка поползёт по всей системе.
Известны тысячи багов типа «дупликации» игровых денег, предметов и т.п. как раз из-за переполнения. Но абсолютно то же самое происходит и в бухгалтерском софте, банковском, системах управления станками и самолётами и т.д. — там, где подобные штуки могут приводить — и приводят — к очень тяжёлым последствиям.
В IEEE 754 переполнения нет именно благодаря бесконечностям. Причем, если где-то всплыла бесконечность, вы от неё уже не избавитесь и хотя бы сразу заметите. Это не идеальный способ, но вычисления в числах с произвольной длиной до сих доступны очень не везде.
Вы ищете теоретический смысл, а он тут сугубо практический.


Ну как бы да. Математика — теоретическая наука.

Напомню, все началось с того, что вы заявили что в матане 1 / 0 — это бесконечность. Я всего лишь хотел указать на вашу ошибку и предостеречь других.

Она не очень-то подходит для обычных вычислений из-за переполнений.


Зато она быстрая. А где это действительно важно — используется арифметика с насыщением. Некоторые DSP даже аппаратно ее реализуют.

Но абсолютно то же самое происходит и в бухгалтерском софте, банковском, системах управления станками и самолётами и т.д. — там, где подобные штуки могут приводить — и приводят — к очень тяжёлым последствиям.


Ну как бы есть библиотеки, которые реализуют saturating arithmetic, есть поддержка проверки переполнения со стороны компиляторов. Надо просто знать инструмент, которым пользуешься.

Кстати, не знаю за станки и самолеты, но финансы в принципе не используют арифметику с плавающей точкой. Только fixed point (или вообще integer, с расчетами в младших единицах валюты).

В IEEE 754 переполнения нет именно благодаря бесконечностям.

Это все безусловно хорошо. Но мы то говорили про деление на ноль?

Было бы правильно сказать что в IEEE 754 приняты соглашения, которые приводят к тому, что деление ненулевого числа на 0 приводит к плюс или минус бесконечности, в зависимости от знака числа и от знака нуля. А матан тут вообще не при чем.

И кстати, два нуля — тоже нехилое отступление от теоретической арифметики.
Математика — теоретическая наука

Прикладные математики мягко скажем удивлены:)
или вообще integer, с расчетами в младших единицах валюты

да, те, которые я видел изнутри, используют целые сотые доли копеек/центов (это позволяет записывать числа типа 12.34%), а десятичная точка выводится только в интерфейсе. И тоже не от хорошей жизни.
два нуля — тоже нехилое отступление от теоретической арифметики.

Это всё же лучше, чем INT_MIN (который -128 в 8-битных целых), который иногда работает как -0, а иногда как нормальное число, и для которого -(-128)=-128

Когда это INT_MIN работает как -0?

При умножении на нечётные положительные или чётные отрицательные числа, например.
0/0 действительно неопределенность, все логично.
А вот дальше я боюсь вы ошибаетесь.
Вот если вы попробуете сделать 2/0 — 1/0, тогда снова будет NaN

Что-то я вижу что любое другое число деля на 0 выходит Infinity
1/0 === Infinity
100/0 === Infinity
1024/0 === Infinity
-512/0 === -Infinity
Да, но если вы возьмёте именно то что я написал (2/0 — 1/0), то будет NaN. Тут вопрос в вычитании, а не в делении. Вычитать бесконечности нельзя.
все. вы имели в виду вычитание бесконечности от бесконечности.
не правильно понял ваш коммент
> Теперь точки могут отмечать новые строки
> Нужно только проставлять флаг /s

Возможно, вы имели в виду:
Теперь точка в регулярных выражениях может захватывать переводы строк, эмодзи и некоторые другие символы, которые раньше не захватывала, если включить флаг /s.
> Кстати, перехваты, в которых вы не учитываете значение e, иногда называют обработкой исключений-покемонов. Потому что вы должны поймать их все!

Вот это тоже странно.

Шутка про исключения-покемоны возникла в джаве, где можно отлавливать исключения по типу. В ES мы всегда «ловим их все», если пишем catch.
Читают, читают тэги, перестаньте уже
Тэги не читают, а теги — читают.
Автору спасибо за обзор последних ES, но вот тема ES2019 не раскрыта.
Там одни chaining (это про '.?'. Кому перечислить денег за внедрение этой фишки?..) и pipelines чего стоят!

Что вы имеете в виду говоря "pipelines"? Если вы про оператор |> — то он до сих пор в stage 1, и в ES2019 не сможет попасть никаким чудом.

Строго говоря, сейчас ничего новое вообще не может попасть в ES2019, так как ES2019 уже финализирован и утвержден. Но если перейти по ссылке, то там написано, что chaining и pipelines не входят в ES2019, странно, что предыдущий комментатор этого не заметил.

const leftPad = (str, len, pad) => Array(len-str.length+1).join(pad)+str
Кому нужны двоичные литералы в языке, который не поддерживает целых чисел?

А в чём заключается противоречие?

Обычно такие литералы используются для битовых масок. Но для JS с его 64-битовыми float непонятно, что логические операции с этими масками в принципе делают.

А что непонятно-то? Результат математической операции не должен зависеть от представления операндов в памяти.


3 | 5 будет 7 хоть в С++, хоть в Javascript

Чему будет равен "-1 | 1", а «2.3 | -1»?

А какая разница-то? Вы бы ещё про "foo" | 1 спросили...

Ну вообще это (выражение a|0) — быстрый способ отбросить дробную часть числа, и, главное, подсказка для интерпретатора, что нужно перейти в целые числа. Если посмотрите asm.js, то там такого полно.

Это уже детали реализации, которые к математике отношения не имеют.

Если числа целые (то есть если у них нет дробной части), то делают именно то, что вы ожидаете от битовых операций над беззнаковыми числами.
Хм, обнаружил, что применение битовых операций к числу в хроме приводит их к целочисленному значению. А значит можно делить целочисленно: a/b | 0, не используя Math.floor, который округляет отрицательные числа не так, как хотелось бы нематематикам.
а ещё num >>> 0 и получем uint32. И полноценная арифметика на интах работает

Это не только в хроме, это в стандарте так. Трюк с |0 даже вошёл в asm.js как указание на целое число. Но это всё следствия динамической типизации, операция | не для этого придумывалась.

В JS-движках (по крайней мере в V8) есть оптимизации, которые вычленяют короткое целочисленное значение из числовых операндов при возможности и оперируют уже с ними. Рантаймовая магия, о которой юзерам языка думать не нужно.

В свежем Chrome уже можно попробовать BigInt: typeof 2n

const regex = /(?<=\$)\d+/;
const text = 'This cost $400';
text.match(regex) === ['400'] // false ибо сравнение с массивом

Будет более верне сравнивать примитивы:

text.match(regex)[0] === '400'
Зарегистрируйтесь на Хабре , чтобы оставить комментарий