Будет ли тип js `Number` дополнять Infinity? - PullRequest
0 голосов
/ 13 октября 2018

Если будет достаточно времени, закончится ли этот цикл?

for (let i = 0; 1 / i > 0; i++) {} // js code [0]

Я думаю, что это произойдет, когда i достигнет Number.POSITIVE_INFINITY, но не знаю, как это проверить.

edit :

for (let i = 0; 1 / i > 0; i += k) {} // js code [1]
  1. Какое наименьшее положительное число k делает js код [1] окончанием?(По крайней мере, k = 1e304 будет)

  2. Давайте предположим, что ответ на вопрос 1 будет K, любое число, большее K, гарантирует завершение кода js [1] ?

Ответы [ 2 ]

0 голосов
/ 13 октября 2018

Наименьшее положительное k, для которого for (let i = 0; 1 / i > 0; i += k) {} завершает это * 1003 2 * 970 + 2 918 , который 9979201547673601274109728685629478266941425536662556495940151194794704206738934042339246016744483498432906272845056291604255807740315814654641757203776116733684667887776747567741590850984835485160546300028847034430406236117424720216135936743286628244379070620554941694189420489857797422317568.

1008 * JavaScript является диалектом ECMAScript , который указывает, что он использует 64-битный (двоичный) формат IEEE-754 с плавающей запятой с округлением до ближайшего связывания с четностью.В этом формате самые большие конечные числа находятся в бинаде от 2 1023 (включительно) до 2 1024 (эксклюзив).Поскольку значимое (дробная часть) числа с плавающей запятой имеет 53 бита, младший значащий бит этих чисел имеет значение позиции 2 1023−52 = 2 971 .Это называется единицей наименьшей точности (ULP).(ULP является функцией показателя степени числа с плавающей запятой; оно масштабируется с числом.)

Когда вычисляется i+k, результат округляется до ближайшего представимого числа.Если k меньше ½ ULP i, то представимое число, ближайшее к математическому значению i + k, равно i, поэтому при выполнении i = i+k никаких изменений не происходит.Если k равно ½ ULP i, то математическое значение i + k находится точно на полпути между i и следующим представимым значением.В соответствии с правилом округления до ближайших связей до четного, оно будет округлено в меньшую сторону, если младший бит i равен нулю, и выше, если он равен единице.Таким образом, если k - это ровно ½ ULP самых больших конечных чисел с плавающей точкой, i = i+k не произведет изменений для половины из них, поэтому цикл не будет выполняться.

Если k превышает ½ULP i, тогда математическое значение i + k ближе к следующему большему представимому значению, чем i, поэтому результат равен i плюс один ULP, поэтому цикл продолжается.(В особом случае, когда i является наибольшим представимым конечным значением, сложение будет производить бесконечность, что затем завершает цикл, поскольку 1 / i будет равен нулю.)

Как указано выше, ULPсамые большие значения - 2 971 .½ ULP составляет 2 970 .Нам нужно, чтобы k было больше этого на наименьшее возможное значение, поэтому мы хотим добавить к нему один ULP.(Один ULP в своем масштабе, а не ULP из самых больших чисел.) ULP 2 970 равен 2 970−52 = 2 918 .

Следовательно, наименьшее положительное значение k, которое приводит к завершению цикла, равно 2 970 + 2 918 .

0 голосов
/ 13 октября 2018

Нет, он никогда не закончится, потому что при больших числах точность числа не срабатывает.Например, добавление 1 к 1e16 приводит к числу, которое также равно 1e16 - после определенной точки оно никогда не будет прогрессировать:

console.log((1e16 + 1) === 1e16);

Эта точка равна 9007199254740992.MAX_SAFE_INTEGER в Javascript - это 9007199254740991.Добавление одного к 9007199254740991 приводит к 9007199254740992, но добавление одного к 9007199254740992 приводит к тому же числу, 9007199254740992:

console.log(9007199254740991 + 1 === 9007199254740992);
console.log(9007199254740992 + 1 === 9007199254740992);

Вы получаете Infinity около 1.7e308.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...