소수점 decimal c# 어떻게하면 큰 수의 평균값을 구할 수 있습니까?




7 Answers

정수 또는 수레?

정수 인 경우 숫자를 읽고 각 값의 개수를 기록하여 도수 분포를 누적해야합니다. 그것은 쉽게 평균화 될 수 있습니다.

부동 소수점의 경우 약간 문제가 있습니다. 수레의 전체 범위와 실제 분포를 감안할 때 모든 수를 유지하지 않고 원하는 정확성을 유지하는 빈 크기를 찾아야합니다.

편집하다

먼저 평균과 표준 편차를 얻기 위해 데이터를 샘플링해야합니다. 수천 점이 충분해야합니다.

그런 다음, 훌륭한 범위를 결정해야합니다. 사람들은 평균 주위에 ± 6σ (표준 편차)와 같은 것을 선택합니다. 이 범위는 가능한 한 많은 양동이로 나뉩니다.

실제로 버킷 수는 평균에서 유효 자릿수를 결정합니다. 따라서 10,000 또는 100,000 버킷을 선택하여 4 또는 5 자리의 정밀도를 얻으십시오. 측정이기 때문에 측정 값이 두 자리 또는 세 자리 만있는 것이 좋을 수 있습니다.

편집하다

처음 샘플의 평균은 다른 샘플의 평균에 매우 가깝습니다. 그리고 모든 표본 평균은 모집단 평균에 가깝습니다. 대부분의 (그러나 전부는 아님) 평균이 서로 1 표준 편차임을 유의하십시오.

측정 오류 및 부정확성은 표준 편차보다 큽니다.

즉 표본 평균은 모집단 평균만큼 유용합니다.

c# math memory

아마도 수 기가 바이트 범위의 큰 수의 숫자가 있습니다. 첫 번째 문제는이 모든 것을 메모리에 저장할 수 없다는 것입니다. 둘째, 이러한 추가를 시도하면 오버플로가 발생합니다. 롤링 평균을 더 많이 사용하려고 생각했지만 정확해야합니다. 어떤 아이디어?

이것들은 모두 부동 소수점 숫자입니다.

데이터베이스에서 읽지는 않으며 여러 소스에서 수집 한 CSV 파일입니다. 그것은 초 단위로 저장되기 때문에 정확해야하며 (예 : 0.293482888929) 롤링 평균은 .2와 .3의 차이가 될 수 있습니다

이것은 사용자가 특정 양식 작업에 응답하는 데 걸린 시간을 나타내는 # 세트입니다. 예를 들어 메시지 상자를 표시 할 때 확인 또는 취소를 누르는 데 걸린 시간. 데이터가 초로 저장되었습니다. 초 단위로 저장되었습니다. 1.2347 초 예를 들면. 그것을 밀리 초로 변환하면 오히려 빨리 int, long 등을 오버플로합니다. 비록 내가 그것을 개조하지 않더라도, 나는 아직도 그것을 오히려 빨리 범람시킨다. 아래의 한 가지 대답은 정확합니다. 100 % 정확할 필요는 없으며, 확실한 StdDev 내부의 특정 범위를 살펴보고 충분히 근접 할 것입니다.




당신은 32 비트와 64 비트 숫자를 의미합니다. 하지만 합리적인 Big Num 라이브러리를 사용하지 않는 이유는 무엇입니까? 데이터가 너무 많아서 정확한 평균을 원한다면 코드를 작성하십시오.

class RationalBignum {
    public Bignum Numerator { get; set; }
    public Bignum Denominator { get; set; }
}

class BigMeanr {
    public static int Main(string[] argv) {
        var sum = new RationalBignum(0);
        var n = new Bignum(0);
        using (var s = new FileStream(argv[0])) {
            using (var r = new BinaryReader(s)) {
                try {
                    while (true) {
                        var flt = r.ReadSingle();
                        rat = new RationalBignum(flt);
                        sum += rat;
                        n++;
                    }
                }
                catch (EndOfStreamException) {
                    break;
                }
            }
        }
        Console.WriteLine("The mean is: {0}", sum / n);
    }
}

컴파일러가 제공하는 것보다 더 많은 숫자 형이 있다는 것을 기억하십시오.




이것은 고전적인 분할 정복 유형 문제입니다.

문제는 큰 숫자 집합의 평균이 집합의 전반부의 평균과 같고 집합의 두 번째 절반의 평균을 평균 한 것입니다.

다른 말로:

AVG(A[1..N]) == AVG( AVG(A[1..N/2]), AVG(A[N/2..N]) )

다음은 간단한 C #, 재귀 적 솔루션입니다. 그것은 내 테스트를 통과했고 완전히 정확해야합니다.

public struct SubAverage
{
    public float Average;
    public int   Count;
};

static SubAverage AverageMegaList(List<float> aList)
{
    if (aList.Count <= 500) // Brute-force average 500 numbers or less.
    {
        SubAverage avg;
        avg.Average = 0;
        avg.Count   = aList.Count;
        foreach(float f in aList)
        {
            avg.Average += f;
        }
        avg.Average /= avg.Count;
        return avg;
    }

    // For more than 500 numbers, break the list into two sub-lists.
    SubAverage subAvg_A = AverageMegaList(aList.GetRange(0, aList.Count/2));
    SubAverage subAvg_B = AverageMegaList(aList.GetRange(aList.Count/2, aList.Count-aList.Count/2));

    SubAverage finalAnswer;
    finalAnswer.Average = subAvg_A.Average * subAvg_A.Count/aList.Count + 
                          subAvg_B.Average * subAvg_B.Count/aList.Count;
    finalAnswer.Count = aList.Count;

    Console.WriteLine("The average of {0} numbers is {1}",
        finalAnswer.Count, finalAnswer.Average);
    return finalAnswer;
}



다음은 의사 코드에서이를 수행하는 한 가지 방법입니다.

average=first
count=1
while more:
  count+=1
  diff=next-average
  average+=diff/count
return average



숫자의 범위에 따라 아래 첨자가 숫자이고 값이 해당 숫자의 수량 인 배열을 갖는 것이 좋습니다. 그러면이 계산을 수행 할 수 있습니다.




왜 부동 소수점 숫자의 합계가 넘치고 있습니까? 이를 위해서는 최대 float 값에 가까운 값을 가져야합니다. 이는 홀수로 들립니다.

정수를 다루는 경우 BigInteger를 사용하거나 집합을 여러 하위 집합으로 나누고 반복적으로 하위 집합을 평균 한 다음 평균을 평균하는 것이 좋습니다.

당신이 수레를 다루는 경우에, 그것은 조금 이상합니다. 롤링 평균은 매우 부정확해질 수 있습니다. 난 오버플로 예외 또는 집합의 끝을 칠 때만 업데이트되는 롤링 평균을 사용하는 것이 좋습니다. 이렇게 효과적으로 세트를 넘치지 않는 세트로 나눕니다.




왜 평균을 계산하기 전에 숫자를 스케일링하지 않을까요?




Related


Tags

c#   math   memory