이것은 수년 동안 내 마음 속에 있었던 일이지만 전에 묻지 않았습니다.
많은 (의사) 난수 생성기는 0.0에서 1.0 사이의 난수를 생성합니다. 수학적으로이 범위에는 무한한 숫자가 있지만 double
부동 소수점 숫자이므로 유한 정밀도를 갖습니다.
따라서 질문은 다음과 같습니다.
double
0.0과 1.0 사이에 몇 개의 숫자가 있습니까?- 1과 2 사이에 숫자가 많습니까? 100과 101 사이? 10 ^ 100과 10 ^ 100 + 1 사이?
참고 : 차이가 있다면 double
특히 Java의 정의에 관심이 있습니다.
답변
Java double
는 IEEE-754 형식이므로 52 비트 분수를가집니다. 2의 인접한 두 거듭 제곱 사이에 (1을 포함하고 다음 것을 제외 함) 따라서 2의 52 제곱 다른 double
s (즉, 4503599627370496)가 있습니다. 예를 들어, double
포함 된 0.5와 제외 된 1.0 사이 의 구별되는 s 의 수 이며 정확히 많은 수가 포함 된 1.0과 제외 된 2.0 사이에 있습니다.
doubles
0.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
뚜렷한 double
s-오는 7036874417766.4004
… 하나 또는 둘을 주거나 받거나 ;-).
답변
모든 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...
답변
다른 사람들은 이미 [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이 생성되지 않음을 의미합니다.
답변
이 기사 자바의 새로운 수학은, 제 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라고합니다.
답변
- 2 ^ 53-은닉 비트를 포함하는 64 비트 부동 소수점 숫자의 유효 / 가수 크기.
- sifnificand는 고정되어 있지만 지수는 변경됩니다.
자세한 내용은 wikipedia 문서 를 참조하십시오.
답변
Java double은 IEEE 754 binary64 숫자입니다.
이는 다음 사항을 고려해야 함을 의미합니다.
- 가수는 52 비트입니다.
- 지수는 1023 바이어스가있는 11 비트 숫자입니다 (예 : 1023이 추가됨).
- 지수가 모두 0이고 가수가 0이 아니면 숫자는 정규화되지 않은 것으로 간주됩니다.
이것은 기본적으로 표준에 따라 0과 1 사이의 가능한 이중 표현의 총 2 ^ 62-2 ^ 52 + 1이 있음을 의미합니다. 2 ^ 52 + 1은 정규화되지 않은 경우를 제거하는 것입니다. 번호.
가수가 양수이지만 지수가 음수이면 양수이지만 1 미만임을 기억하십시오 🙂
다른 숫자의 경우 가장자리 정수가 IEEE 754 표현에서 정확한 방식으로 표현되지 않을 수 있고 지수에 숫자를 표현할 수있는 다른 비트가 사용되기 때문에 조금 더 어렵습니다. 다른 가치.