/// <summary>
        /// 自然対数のテーラー展開。
        /// ln(input) = ln 2^count2 (1+x) ≒ count2 * ln2 + (x - x^2/2 + x^3/3 - x^4/4 + ・・・)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static decimal NaturalLogarithm(decimal input)
        {
            //引数が0以下が定義できないので、例外を返す
            if (input <= 0)
            {
                throw new FormatException("Input " + nameof(input) + ";" + input.ToString("G6") + "must be equal to or more than zero");
            }


            //引数が1より小さい場合、絶対値の大きな負の数が返される。
            //近似の制度が下がるので、ln(input) = -ln(1/input)=-ln(1+x)
            //とおいて計算する。
            decimal onePlusX = input;
            decimal sign     = 1m;

            if (input < 1)
            {
                onePlusX = 1m / input;
                sign     = -1;
            }

            //input = 2^count2 * (1+x)
            //の形に変形する。
            uint count2 = 0;

            while (onePlusX > 2m)
            {
                count2++;
                onePlusX /= 2m;
            }
            decimal x = onePlusX - 1m;


            decimal numerator = x;

            decimal result = count2 * TaylorSeriesDecimal.Ln2();

            //テーラー展開
            result += x;
            for (int j = 2; j <= (int)Math.Ceiling(10m * x); j++)
            {
                numerator *= x;
                if (j % 2 == 0)
                {
                    result -= numerator / j;
                }
                else
                {
                    result += numerator / j;
                }
            }

            //符号を反映する.
            result *= sign;

            return(result);
        }
Ejemplo n.º 2
0
        public decimal Calculate_f_u(decimal[] input)
        {
            decimal index = 0.0m;

            for (int j = 0; j < input.Length; j++)
            {
                index += input[j] * input[j];
            }

            return(TaylorSeriesDecimal.Exponential(-index / 2m));
        }
        /// <summary>
        /// 平方根のテーラー展開。
        /// √input = √2^count2 * (1+x) = √2^count2 * ( 1 + x/2 - x^2/8 + x^3/16 - x^4/128 + ・・・)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static decimal SquareRoot(decimal input)
        {
            if (input == 0m)
            {
                return(decimal.Zero);
            }
            else if (input < 0)
            {
                throw new FormatException("Input " + nameof(input) + ";" + input.ToString("G6") + "must be equal to or more than zero .");
            }


            //input = 2^count2 * (1+x)
            //の形に変形する。
            decimal onePlusX = input;

            if (input < 1)
            {
                onePlusX = 1m / input;
            }

            uint count2 = 0;

            while (onePlusX > 2m)
            {
                count2++;
                onePlusX /= 2m;
            }
            decimal x = onePlusX - 1m;

            //テーラー展開
            decimal numerator = x;
            decimal result    = 1m + x / 2m;

            numerator *= x;
            result    -= numerator / 8m;
            numerator *= x;
            result    += numerator / 16m;
            numerator *= x;
            result    -= numerator / 128m;

            //√2^count2 をかける
            for (uint j = 0; j < count2 / 2; j++)
            {
                result *= 2m;
            }
            for (uint j = 0; j < count2 / 2 - 1; j++)
            {
                result *= TaylorSeriesDecimal.Sqrt2();
            }

            return(result);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// 乱数を生成する
        /// 平均値 average
        /// 標準偏差 std
        /// </summary>
        /// <param name="average"></param>
        /// <param name="std"></param>
        /// <returns></returns>
        public decimal NextDecimal(decimal average, decimal std)
        {
retry_point:

            decimal u1 = ud1.NextDecimal();
            decimal u2 = ud2.NextDecimal();

            decimal v1 = 2 * u1 - 1;
            decimal v2 = 2 * u2 - 1;
            decimal v  = v1 * v1 + v2 * v2;

            if (v <= 0 || 1 <= v)
            {
                goto retry_point;
            }

            decimal w = TaylorSeriesDecimal.SquareRoot(-2 * TaylorSeriesDecimal.NaturalLogarithm(v) / v);

            decimal y1 = v1 * w;
            decimal y2 = v2 * w;


            if (even)
            {
                resultDecimal = y1;
                even          = false;
            }
            else
            {
                resultDecimal = y2;
                even          = true;
            }

            resultDecimal = TaylorSeriesDecimal.Exponential(resultDecimal * Math.Abs(std) + average);
            return(resultDecimal);
        }