2013-02-28 5 views
-1

나는 두 배의 긴 순서를 가지고 있습니다 (100 000보다 길지 않다고 가정합니다). 또한 각 숫자가 200 000보다 크지 않다고 가정합시다. 아래의 알고리즘이 이러한 계산에 적합한 경우? 충분히 정확할까요?두 배의 순서의 무게 평균을 계산하십시오

예를 들어 100 000 번 200 000의 합계를 100 000으로 나누면 199 999와 200 001 사이의 값을 갖지만 200 100이나 그와 같은 값은 없을 것으로 예상됩니다 (이러한 특정 숫자는 내 클래스 테스트를 위해 MarcinJuraszek에게 감사드립니다.)

class Candle 
{ 

    public Candle(double value) 
    { 
     ValueUpdated(value); 
    } 

    private double sum = 0; 
    private double count = 0; 

    public void ValueUpdated(double value) 
    { 
     sum += value; 
     count++; 
    } 

    public double WeightAverage 
    { 
     get { return sum/count; } 
    } 

} 
+1

C#에서 double의 정밀도는 소수점 이하 15-16 자입니다. 당신이 6 번째 소수점 자리에서만 정밀도를 찾고 있기 때문에, 이것이 당신에게 문제가 될 것이라고는 상상할 수 없습니다. –

+0

참고 이것은 일반적으로 일반적으로 "가중 평균"이 아니라 "롤링"또는 "이동"평균이라고합니다. @DavidHope가 말했듯이 당신이 찾고있는 정밀도는 괜찮을 것이다. 그러나 어떤 이유에서'2147483647' 이상의 아이템의 평균을 계산한다면 실패 할 것이다. – NominSim

+0

몇 가지 빠른 테스트를 수행하고 500,000 개의 테스트 항목을 사용하여 16 번째 소수점 이하 자릿수에서 오류가 발생했습니다 –

답변

1

두 배 정밀도 부동 소수점 수는 52 자의 소수 비트를 갖습니다. 즉, 대략 log10 (2^52) ~ = 16 소수 자릿수의 정밀도를가집니다. 소수점 6 자리 만 필요하기 때문에 완벽하게 괜찮습니다.

왜 테스트하지 않습니까?

double sum = 0.0; 
int count = 100000; 
for (int i = 0; i < count; ++i) { 
    sum += 200000.0; 
} 
double average = sum/(double)count; 
Console.WriteLine(average); // prints out exactly 200000 
+0

VM 실행 코드 테스트가 아무 것도 증명하지 않기 때문에. 다른 사람은 사양에 의존해야하는 다른 VM을 가질 수 있습니다. – javapowered

+0

@javapowered이 코드의 기능은 C# 사양에 따라 정의됩니다. C#은 double을 IEEE754 64 비트 float 인 System.Double (http://msdn.microsoft.com/en-us/library/system.double.aspx)으로 정의합니다. 따라서 항상이 숫자 형식의 정밀도를 사용하여이 테스트를 통해 C# 및 CLR의 유효한 구현에 대해 동일한 결과를 얻을 수 있습니다. – Asik

0

확실히 루프에 버그가 있습니다. 그냥 시도 :

var candle = new Candle(200000); 

for (int i = 1; i < 100000; i++) 
    candle.ValueUpdated(200000); 

Console.WriteLine(candle.WeightAverage); 

결과는 예측 가능하고 올바른 : 200000!

MSDN에 따르면 배정도는 15-16 자리까지 설정되며, 필요한 것보다 훨씬 더 많습니다.

+0

이었습니다. 나는 당신의 루프를 전혀 시도하지 않았습니다. 나는 그것이 실패 할 것이라고 짐작했다. 할 수 없다면 그것은 좋은 소식입니다. 아마도 누군가가 거액의 "누적"없이 다른 더 나은/더 빠른 방법을 제안 할 수 있습니다. – javapowered

0

언급 한 바와 같이 double은 15-16 자릿수의 정밀도를 갖습니다. 따라서 범위 값 (직선 값 또는 가중 평균 값의 가중치)은 15 자리 이하 여야합니다.

관련 문제