Ejemplo n.º 1
0
        /// <summary>Fills data by current distribution.</summary>
        /// <param name="numbers">Data that should be filled</param>
        /// <param name="cnt">Number or repetitions. Returned the number of random generator calls.</param>
        /// <returns>Average Y value.</returns>
        public static float GetDistrib(Numbers numbers, ref int cnt)
        {
            GenCallCnt = 0;
            if (Library == ON_C)
            {
                float res = CRandom.GetDistrib(
                    numbers != null ? numbers.Data : null, ref cnt, ref GenCallCnt);
                cnt = GenCallCnt;
                return(res);
            }
            else if (Library == ON_SCH_STRONG)
            {
                CshStrongRandomGen gen = new CshStrongRandomGen(cnt);
                RandomNumb = gen.GetNext;
            }
            decimal sum = 0;
            int     val;
            int     actualCnt = 0;
            double  dval;
            float   ssDev; // result of inverse normal distrib
            int     min, max;

            for (int i = 0; i < cnt; i++)
            {
                dval = Distrib() * DistVars[1] + DistVars[0];
                if (IsExp)  // lognorm is able
                {
                    val = (int)Math.Exp(dval);

                    if (ssMean > 0)                      // size selection is able
                    // === simple method
                    //if (GetRandom() > ssAlignRatio *
                    //    Math.Exp(-Math.Pow(dval - ssMean, 2) / ssDVariance) / ssFactor)
                    //    continue;		// filter by size selection

                    // === method with using min and max
                    {
                        ssDev = ssFactor0 * (float)Math.Sqrt(Math.Log(ssFactor1 / GetRandom()));
                        min   = (int)(ssMean - ssDev);
                        max   = (int)(ssMean + ssDev);
                        if (val < min || val > max)
                        {
                            continue;                                   // filter by size selection
                        }
                    }
                }
                else // lognorm is disable
                {
                    val = (int)dval;
                    // round up val: otherwise all values will be round down during casting to int.
                    // in this case the distribution will not only be inaccurate,
                    // but worse - values less than 1 will be rounded to 0,
                    // which leads to a falsely large number of zero points.
                    // The variant val = (int)Math.Round(dval, 0) is much slower
                    if (dval > 0)
                    {
                        if (dval - val >= 0.5)
                        {
                            val++;
                        }
                    }                                                   // round up positives
                    else
                    {
                        if (dval - val <= -0.5)
                        {
                            val--;
                        }
                    }                                           // round up negatieves
                }
                sum += val;
                if (numbers != null)
                {
                    numbers.Data[actualCnt] = val;
                }
                actualCnt++;
            }
            cnt = GenCallCnt;
            return((float)sum / actualCnt);
        }