0.0과 1.0 사이에는 몇 개의 이중 숫자가 있습니까?


94

이것은 수년 동안 내 마음 속에 있었던 일이지만 전에 묻지 않았습니다.

많은 (의사) 난수 생성기는 0.0에서 1.0 사이의 난수를 생성합니다. 수학적으로이 범위에는 무한한 숫자가 있지만 double부동 소수점 숫자이므로 유한 정밀도를 갖습니다.

따라서 질문은 다음과 같습니다.

  1. double0.0과 1.0 사이에 몇 개의 숫자가 있습니까?
  2. 1과 2 사이에 숫자가 많습니까? 100과 101 사이? 10 ^ 100과 10 ^ 100 + 1 사이?

참고 : 차이가 있다면 double특히 Java의 정의에 관심이 있습니다.

답변:


68

Java doubleIEEE-754 형식이므로 52 비트 분수를가집니다. 2의 인접한 두 거듭 제곱 사이에 (1을 포함하고 다음 것을 제외 함) 따라서 2의 52 제곱 다른 doubles (즉, 4503599627370496)가 있습니다. 예를 들어, double포함 된 0.5와 제외 된 1.0 사이 의 구별되는 s 의 수 이며 정확히 많은 수가 포함 된 1.0과 제외 된 2.0 사이에 있습니다.

doubles0.0에서 1.0 사이를 세는 것은 2의 거듭 제곱 사이에서 계산하는 것보다 어렵습니다. 그 범위에 포함 된 2의 거듭 제곱이 많고 비정규 화 된 숫자의 까다로운 문제에 빠지기 때문입니다. 지수의 11 비트 (10)는 비정규 번호를 포함, 그래서 문제의 범위를 커버하지 (나는 몇 가지를 생각 NaN하면 1024 배에있는 것) double두 세력 사이에 누워들 - 더 이상의 2**62총 어쨌든에서 . 비정규 화 된 & c를 제외하면 카운트는 1023 회라고 생각합니다 2**52.

"100에서 100.1"과 같은 임의의 범위의 경우 상한이 정확히 a double(2의 거듭 제곱의 정확한 배수가 아님)로 표시 될 수 없기 때문에 더 어렵습니다 . 편리한 근사치로, 2의 거듭 제곱 사이의 진행이 선형이므로, 범위는 0.1 / 64주변 2의 거듭 제곱 (64 및 128) 사이의 범위의 th 라고 말할 수 있습니다.

(0.1 / 64) * 2**52

뚜렷한 doubles-오는 7036874417766.4004... 하나 또는 둘을 주거나 받거나 ;-).


@Alex : 참고로 100 ~ 100.1을 썼을 때 잘못 썼습니다. 100에서 101까지 의미했습니다. 기본적으로 임의의 N에 대해 N과 N + 1 사이입니다.
polygenelubricants

4
@Alex : 그러니 솔직히 말씀 드리겠습니다. 2**64가능한 double 값 이상은있을 수 없습니다 (64 비트 유형이기 때문에). 분명히 그 값의 엄청난 비율은 0..1?
polygenelubricants 2010 년

9
@polygene, yes 및 yes-구체적으로 가능한 값의 약 1/4 (기수 및 지수 대 분수 길이의 "정상"부동 소수점 표현에 대해) 0.0과 1.0 (1.0과 무한대 사이의 또 다른 1/4)에 있습니다. 실제 축의 음의 절반에 나머지 절반). 본질적으로 지수 값의 절반 (정상 편향, 범위 내 절반)은 밑의 음수를 나타내므로 숫자는 1.0 미만입니다.
Alex Martelli

8
@polygenelubricants : 많은 응용 분야에서 0에서 1 사이의 범위는 100에서 101 사이의 범위보다 훨씬 더 중요하고 흥미 롭기 때문에 값의 더 큰 부분을 차지합니다. 예를 들어, 물리학에서 6.67e-11에서 뉴턴의 중력 상수와 같이 엄청나게 작은 값을 처리해야하는 경우가 많습니다. 좋은 정밀도를 갖는 것이 100에서 101 사이보다 더 유용 합니다. 자세한 내용은 floating-point-gui.de 를 읽으십시오 .
Michael Borgwardt 2010-06-05

1
또한 0.0에서 1.0 사이의 숫자로 배율을 조정하여 배율을 별도로 추적하여 계산 오류를 줄일 수 있습니다. 전체 수선을 두 숫자 사이에 매핑 할 수있는 것이 좋습니다!
codekaizen 2010

42

모든 double그 대표 값 사이 0x00000000000000000x3ff0000000000000구간 [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이 서로 다른 표현을 가짐을 기억하십시오.)
Jim Lewis

1
+1, 그런 트위스트 엔딩! M. Night Shyamalan 대본을 읽는 것처럼 느껴졌습니다!
polygenelubricants

7

다른 사람들은 이미 [0.0, 1.0] 범위에 약 2 ^ 62 두 배가 있다고 설명했습니다.
(정말 놀라운 일이 아닙니다. 거의 2 ^ 64 개의 고유 한 유한 복식이 있습니다.이 중 절반은 양수이고 중 절반은 1.0 미만입니다.)

그러나 난수 생성기를 언급합니다. 0.0에서 1.0 사이의 숫자를 생성하는 난수 생성기 는 일반적으로 이러한 모든 숫자를 생성 할 수 없습니다 . 일반적으로 정수 n을 가진 n / 2 ^ 53 형식의 숫자 만 생성합니다 (예 : nextDouble에 대한 Java 문서 참조 ). 따라서 일반적으로 random()출력에 대해 가능한 값은 약 2 ^ 53 (포함되는 끝점에 따라 +/- 1) 정도입니다 . 이는 [0.0, 1.0]에서 대부분의 double이 생성되지 않음을 의미합니다.


3

이 기사 자바의 새로운 수학은, 제 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);
    }
}

그들은 그것에 대해 다음과 같은 의견을 가지고 있습니다.

1.0에서 2.0까지 정확히 8,388,609 개의 플로트가 있습니다. 크지 만이 범위에 존재하는 실수의 무한대는 거의 없습니다. 연속 된 숫자는 약 0.0000001 간격입니다. 이 거리를 최하위 정밀도 단위 또는 마지막 위치의 단위에 대한 ULP라고합니다.


네,하지만 대한의 float, 아니 double - float들 때문에, 분수의 23 비트 '의 가치가 2**23 -> 8388608두 개의 인접한 힘 사이의 서로 다른 값 (물론 "포함"부분은 당신이 더 많은이의 다음 전원을 계산해야 의미). double에는 52 비트 분수가 있습니다!
Alex Martelli

1
@Alex

1
나는 멍청하다고 느낀다. 난 그냥 쓴 double동등하고 생각했다 "이봐, 내가 약 5 분 내 자신의 질문에 대답거야 ..."
polygenelubricants

1
@polygene : 확실한 방법은 ... 계산 불가능하지만, 임의의 경우를 해결하기 위해 몇 가지 훌륭하게 간단한 공식이 있어야 프로젝트 오일러 문제 등이 Feel로
마크 Rushakoff

2
어쩌면 진정한 슈퍼 슈퍼하지 : 기계가, 내부 루프를 실행하는 단지 나노초을 복용 계산에 double두 개의 인접한 힘 사이 오십이일 정도 걸릴 것이라고합니다 ( println물론이 될 것이다 매우 매우 빠르고, 상관없이 어떤 것을 실행하지 않을 한 문장이 사라진다고 가정 해 봅시다 .-). 강력하지만 현실적인 기계에서 1 년 이하가 걸릴 수 있다고 생각합니다 .-).
Alex Martelli

2
  1. 2 ^ 53-은닉 비트를 포함하는 64 비트 부동 소수점 숫자의 유효 / 가수 크기.
  2. sifnificand는 고정되어 있지만 지수는 변경됩니다.

자세한 내용은 wikipedia 문서 를 참조하십시오.


2에 대한 귀하의 답변은 FP의 작동 방식을 이해하는 방법과 모순됩니다.
polygenelubricants 2010 년

내 생각 1숨겨진 비트가 항상 하나이기 때문에 잘못된 - 따라서 2^52, 없는 2^53 별개의 값 (인접한 두 개의 힘을 포함 하나 제외 다음 하나 사이 - 하지 ! 0.0 ~ 1.0).
Alex Martelli

1

Java double은 IEEE 754 binary64 숫자입니다.

이는 다음 사항을 고려해야 함을 의미합니다.

  1. 가수는 52 비트입니다.
  2. 지수는 1023 바이어스가있는 11 비트 숫자입니다 (예 : 1023이 추가됨).
  3. 지수가 모두 0이고 가수가 0이 아니면 숫자는 정규화되지 않은 것으로 간주됩니다.

이것은 기본적으로 표준에 따라 0과 1 사이의 가능한 이중 표현의 총 2 ^ 62-2 ^ 52 + 1이 있음을 의미합니다. 2 ^ 52 + 1은 정규화되지 않은 경우를 제거하는 것입니다. 번호.

가수가 양수이지만 지수가 음수이면 양수이지만 1 미만임을 기억하십시오 :-)

다른 숫자의 경우 가장자리 정수가 IEEE 754 표현에서 정확한 방식으로 표현되지 않을 수 있고 지수에 숫자를 표현할 수있는 다른 비트가 사용되기 때문에 조금 더 어렵습니다. 다른 가치.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.