2013-03-22 10 views
1

실수 값 행에 대한 float 값 분포를 더 잘 이해하려고합니다.균일 분포 된 최대 값 범위?

public class Foo { 
    public static void main(String[] args) 
    { 
     for(int i=0; i<24; i++) 
     { 
      int count = 0; 
      float R = (float) Math.pow(10, i); //(2<<i); 
      float Rstep = Math.ulp(R); 
      for(float x = -R; x <= R; x+=Rstep) 
       count++; 
      System.out.println(R+" "+count+" "+Math.ulp(R)); 
     } 
    } 
} 
:

난 R은 10의 힘 (도 2의 거듭 제곱으로 시도)되는 범위 균일 분포 표현할 수있는 값의 개수 (-R, R)를 계산하는 코드를 작성 나는 반 확신 자신이 균일하게 분포 값의 수있을 것 거라고로

가 나는 결과에 분산에 의해

1.0 16777217 1.1920929E-7 
10.0 20971521 9.536743E-7 
100.0 26214401 7.6293945E-6 
1000.0 32768001 6.1035156E-5 
10000.0 20480001 9.765625E-4 
100000.0 25600001 0.0078125 
1000000.0 32000001 0.0625 

하여 예 놀랐다 16777216 (즉, 1,321 0 <23, 23 비트 가수의 경우, 부호 비트로 인해 두 배가 됨).

이 질문에 대한 약간의 설명을하기 위해 - 모델을 작성하려고합니다 (예 : 킬로미터에서 나노 미터 단위 거리의 SI 단위를 사용하는 모델).하지만이를 플로트 공간으로 매핑해야합니다. GPU). 이 모델은 과학적인 모델이므로 정밀도가 손실 된 부분을 이해해야합니다. 계획은 균일하게 분포 된 범위에 값을 스냅하는 것입니다. 따라서 위의 표에서 스냅 (-1000,1000)을 사용하면 32768001 정확한 값을 얻을 수 있습니다.

이 범위에서 너무 많은 차이가있을 수 있고 2 가지 경우의 힘이 제한되는 이유는 반 직관적 인 것처럼 보입니다.

누구나 이것에 대해 어떻게 생각하는지 설명 할 수 있습니까?

환호

+0

0을 잊어 버린 것 같습니다. – alestanis

+0

감사합니다. 나는이 잠재적 인 off-by-one 오류에 대해 그렇게 걱정하지 않습니다. (이해하는 것이 좋겠지 만) 2의 요인의 차이가 더 많습니다. – user2152466

+0

"균일하게 분포 된"이란 무엇을 의미합니까? 'float'값이 균일 한 간격을 갖는 0을 포함하는 유일한 간격은 -2 ** - 125 (약 -2.35e-38)에서 +2 ** - 125까지이며 그 모든 하위 간격입니다. 그 간격에서, 간격은 2 ** - 149 (약 1.40e-45)이다. 그 너머에 단계 크기가 다릅니다. 표현 가능한 값의 분포가 일정하지 않습니다. –

답변

2

당신은 정말 16 진수로 수레를 인쇄해야합니다, 그것은 다음 훨씬 명확하게 될 것이다.

"16777216 (23 비트 가수의 경우 1 < <23, 부호 비트로 인해 두 배가 됨)"의 예상치는 예상 한 것의 절반에 불과합니다. 가장 좋은 경우는 -0x1.FFF ... pX (16 진수)로 시작하는 숫자부터 시작하는 것입니다. 즉, 2의 거듭 제곱 바로 아래의 숫자와 반대입니다. 반복적으로 초기 ULP를 추가 할 때, 지수 X를 사용하여 유효 값의 모든 값을 실제로 트래버스합니다. 추측 한대로 1 < < 23 단계입니다. 이 작업을 완료하면을 시작할 때 이 0에 가까워집니다. 동일한 수의 단계로 0이되며 (지수가 X보다 작음) 양의 값에 대해 다시 단계 수가 두 배가됩니다.

그래서 1의 근처에있는 힘과 그 반대의 사이에서 발견 할 수있는 1 < < 25 (~ 32000000) 또는 그렇게 고른 간격의 수레입니다. 1000은 2의 거듭 제곱의 바로 아래에 있기 때문에 1000의 단계 수를 얻을 수 있습니다.

최악의 경우는 두 번째의 힘을 가진 숫자로 시작하는 것입니다 (예 : 0x1.00001pX). 그런 다음 지수 X로 거의 값을 통과하지 않고 더 낮은 지수로 즉시 값을 방문하기 시작합니다. 표기 -0x1.123defpX가 -0x1.123def으로 해석되어야한다 * 2^X. : 당신은


주이 0x1.FFF에서 시작했다면 당신이하는 것처럼 절반 밖에 많은 값 ... pX의 방문 결국 프로그래밍 언어에서 부동 소수점 값의 입력 및/또는 출력을 허용 할 수 있습니다. 다시 반복하기 위해 일어나는 일을 이해하려고 할 때 매우 편리합니다.