Скільки подвійних чисел між 0,0 і 1,0?


94

Це те, що мені запам’яталось роками, але я ніколи раніше не знайшов часу, щоб запитати.

Багато генераторів випадкових чисел (псевдо) генерують випадкове число від 0,0 до 1,0. Математично в цьому діапазоні є нескінченні числа, але doubleце число з плаваючою комою і, отже, має кінцеву точність.

Тож питання такі:

  1. Скільки всього doubleчисел між 0,0 і 1,0?
  2. Чи стільки ж цифр від 1 до 2? Між 100 і 101? Між 10 ^ 100 і 10 ^ 100 + 1?

Примітка: якщо це має значення, мене цікавить, doubleзокрема , визначення Java .

Відповіді:


68

Java doubleмають формат IEEE-754 , тому вони мають 52-бітову частку; між будь-якими двома сусідніми степенями двох (включаючи одну та doubleвиключуючи наступну), отже, буде від 2 до 52- ї потужності різних s (тобто 4503599627370496 з них). Наприклад, це кількість різних doubles між 0,5 включеними та 1,0 виключеними, і саме стільки також лежить між 1,0 включеною та 2,0 виключеною тощо.

Підрахувати doublesвід 0,0 до 1,0 складніше, ніж зробити це між степенями двох, тому що в цей діапазон включено багато степенів двох, і, крім того, одна потрапляє в непрості питання денормалізованих чисел. 10 з 11 бітів показників охоплюють діапазон, про який йде мова, тому, включаючи денормалізовані числа (і, я думаю, кілька видів NaN), у вас буде 1024 рази більше doubles, ніж між степенями двох - не більше, ніж 2**62загалом . За винятком денормалізованих & c, я вважаю, що кількість буде 1023 рази 2**52.

Для довільного діапазону, такого як "100 до 100,1", це ще складніше, тому що верхня межа не може бути точно представлена ​​як a double(не є точним кратним будь-якій потужності двох). Як зручне наближення, оскільки прогресія між степенями двох є лінійною, ви можете сказати, що зазначений діапазон складає 0.1 / 64th діапазону між оточуючими степенями двох (64 і 128), тож ви очікуєте приблизно

(0.1 / 64) * 2**52

чітке doubles - яке зводиться до 7036874417766.4004... дати або взяти один або два ;-).


@Alex: лише на замітку, коли я писав від 100 до 100,1, я писав неправильно. Я мав на увазі від 100 до 101. В основному, між N і N + 1 для довільних N.
— полігенмастильні

4
@Alex: тож дозвольте мені це зрозуміти: може бути не більше 2**64можливих подвійних значень (оскільки це 64-бітний тип), і, мабуть, ВЕЛИЧЕЗНА частка цих значень лежить між ними 0..1?
— полігенмастильні речовини

9
@polygene, так і так - зокрема, приблизно одна чверть можливих значень (для будь-якого "нормального" подання з плаваючою точкою будь-якої бази та показника проти довжини дробу) лежить між 0,0 і 1,0 (інша чверть між 1,0 і нескінченністю, а половина, що залишилася на від’ємній половині реальної осі). По суті, половина значень показника (з нормальним зміщенням, наполовину в межах його діапазону) представляють від'ємні потужності основи, отже, числа <1,0.
— Alex Martelli,

8
@polygenelubricants: для багатьох застосувань діапазон від 0 до 1 набагато, набагато важливіший і цікавіший, ніж діапазон від 100 до 101, тому він отримує більшу частку значень. Наприклад, у фізиці часто доводиться мати справу із смішно малими значеннями, такими як гравітаційна константа Ньютона при 6.67e-11. Маючи хорошу точність, корисніше, ніж між 100 і 101. Прочитайте floating-point-gui.de для отримання додаткової інформації.
— Michael Borgwardt

1
Ви також можете масштабувати будь-яке число від 0,0 до 1,0, відстежуючи шкалу окремо, даючи менше помилок при обчисленні. Приємно, коли весь числовий рядок може бути зіставлений між двома числами!
— codekaizen

42

Кожне doubleзначення, подання якого знаходиться між 0x0000000000000000і 0x3ff0000000000000лежить в інтервалі [0,0, 1,0]. Це (2 ^ 62 - 2 ^ 52) різні значення (плюс-мінус пари залежно від того, чи вважаєте ви кінцеві точки).

Інтервал [1.0, 2.0] відповідає поданням між 0x3ff0000000000000і 0x400000000000000; це 2 ^ 52 різні значення.

Інтервал [100,0, 101,0] відповідає поданням між 0x4059000000000000і 0x4059400000000000; це 2 ^ 46 різних значень.

Не існує подвоєнь між 10 ^ 100 і 10 ^ 100 + 1 . Жодне з цих чисел неможливо представити з подвійною точністю, і між ними немає подвійних. Найближчими двома числами подвійної точності є:

99999999999999982163600188718701095...

і

10000000000000000159028911097599180...

+1, за добре підкріплену точну відповідь. (Якщо ви вимогливі до підрахунку кінцевих точок, пам’ятайте, що +0.0 та -0.0 мають різні подання.)
— Джим Льюїс,

1
+1, такий поворот закінчується! Відчував, ніби я читаю сценарій М. Нічного Шьямалана!
— полігенмастильні речовини

7

Інші вже пояснювали, що в діапазоні є приблизно 2 ^ 62 подвійних [0,0, 1,0].
(Це насправді не дивно: існує майже 2 ^ 64 чітких скінченних подвійних; з них половина є позитивними, і приблизно половина з них <1,0.)

Але ви згадуєте генератори випадкових чисел: зауважте, що генератор випадкових чисел, що генерує числа від 0,0 до 1,0, загалом не може створити всіх цих чисел; як правило, це буде видавати лише числа форми n / 2 ^ 53 з n цілим числом (див., наприклад, документацію Java для nextDouble ). Отже, зазвичай існує лише близько 2 ^ 53 (+/- 1, залежно від того, які кінцеві точки включені) можливих значень для random()вихідних даних. Це означає, що більшість подвійних значень у [0.0, 1.0] ніколи не буде створено.


3

Стаття Нова математика Java, Частина 2: Числа з плаваючою комою від IBM пропонує такий фрагмент коду, щоб вирішити це (у плаваючих, але я підозрюю, що це працює і для подвійних):

public class FloatCounter {

    public static void main(String[] args) {
        float x = 1.0F;
        int numFloats = 0;
        while (x <= 2.0) {
            numFloats++;
            System.out.println(x);
            x = Math.nextUp(x);
        }
        System.out.println(numFloats);
    }
}

Вони мають про це коментар:

Виявляється, існує рівно 8 388 609 плаваючих місць від 1,0 до 2,0 включно; велика, але навряд чи незліченна нескінченність дійсних чисел, що існують у цьому діапазоні. Послідовні числа складають приблизно 0,0000001. Ця відстань називається ULP для одиниці найменшої точності або одиниці останнього місця.


Так, але це для float, а не double - floatчастка має 23 біти, тому 2**23 -> 8388608різні значення між сусідніми степенями двох ("включна" частина, звичайно, означає, що вам доведеться порахувати ще одну, наступну ступінь двох). doubles мають 52-розрядні дроби!
— Alex Martelli,

1
@Alex: Гадаю, мені доведеться залишити програму (модифіковану для парних), що працює до кінця Всесвіту, або близько того, перш ніж я зможу отримати результати ... :(
— Марк Рушаков,

1
Я почуваюся німо; Я просто написав doubleеквівалент і подумав: "Гей, я відповім на власне запитання приблизно за 5 хвилин ..."
— полігенмастильні матеріали,

1
@polygene: Це схоже на проблему Ейлера проекту, де очевидний підхід неможливо обчислити, але повинна бути якась
— надзвичайно

2
можливо, не з по-справжньому надзарядженим суперкомп'ютером: на машині, яка займає лише наносекунду, щоб запустити внутрішній цикл, підрахунок doubleміж сусідніми потужностями двох займе близько 52 днів ( printlnзвичайно, дуже малоймовірно, щоб він працював так швидко, незважаючи ні на що, тому припустимо, що одне твердження зникає ;-). Я думаю, що можливо взяти рік чи менше на потужній, але реалістичній машині ;-).
— Alex Martelli

2
  1. 2 ^ 53 - розмір значення / мантиси 64-бітного числа з плаваючою комою, включаючи прихований біт.
  2. Приблизно так, оскільки sifnificand фіксований, але показник змінюється.

Докладнішу інформацію див. У статті Вікіпедії .


Ваша відповідь за 2 суперечить тому, як я розумію роботу FP.
— полігенмастильні речовини

Я думаю , що 1це неправильно , тому що прихований біт завжди один - тому 2^52, НЕ 2^53 окремі значення (між сусідніми ступенями двійки, один включав і наступний виключеного - НЕ ! Від 0.0 до 1.0).
— Alex Martelli

1

Двомісний Java - це двійковий64 номер IEEE 754.

Це означає, що нам потрібно врахувати:

  1. Мантіса - 52 біт
  2. Показником є ​​11-бітове число з 1023 зміщенням (тобто з доданим до нього 1023)
  3. Якщо показник степеня дорівнює 0, а мантиса не дорівнює нулю, то число називають ненормованим

Це в основному означає, що в цілому існує 2 ^ 62-2 ^ 52 + 1 можливих подвійних подань, які згідно зі стандартом знаходяться між 0 і 1. Зверніть увагу, що 2 ^ 52 + 1 для видалення випадків ненормованого числа.

Пам'ятайте, що якщо мантиса додатна, але показник від'ємний, число є додатним, але менше 1 :-)

Для інших чисел це трохи складніше, тому що цілі числа краю не можуть бути точно представлені у поданні IEEE 754, і оскільки в експоненті є інші біти, які можуть представляти числа, тому чим більше число, тим менше різні значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.