エレファント・ビジュアライザー調査記録

ビジュアルプログラミングで数式の変形を表すことを考えていくブロクです。

関数プログラミングと無限論理多項式(31)

C# の例(10)

Numbers クラスを変更しないようにします。

    internal class Numbers
    {
        private readonly LongDecimal number;
        private readonly LongDecimal square_difference;
        private readonly int scale;
        public Numbers(LongDecimal number, LongDecimal square_difference, int scale)
        {
            this.number = number;
            this.square_difference = square_difference;
            this.scale = scale;
        }
        public Tuple<int, Numbers> GetNextDecimalDigitAndNumbers()
        {
            LongDecimal two = new LongDecimal(2);
            for (int dd = 9; dd >= 0; dd--)
            {
                LongDecimal zd = new LongDecimal(dd).Shift(scale);
                LongDecimal number_sq_diff = number * zd * two + zd * zd;
                if (number_sq_diff <= square_difference)
                {
                    return new Tuple<int, Numbers>(dd, new Numbers(number + zd, square_difference - number_sq_diff, scale + 1));
                }
            }
            return null;
        }
    }

NumbersGenerator クラスの GenerateDecimal メソッドは以下のようにします。

        public IEnumerable<int> GenerateDecimal()
        {
            LongDecimal number = new LongDecimal();
            LongDecimal square_difference = new LongDecimal(3);
            Numbers nums = new Numbers(number, square_difference, 0);
            for(; ;)
            {
                Tuple<int, Numbers> d_ns = nums.GetNextDecimalDigitAndNumbers();
                nums = d_ns.Item2;
                yield return d_ns.Item1;
            }
        }

Calc クラスの RepeatServer メソッドと NextDigitAndNumbers は以下のようにします。

        public string RepeatServer()
        {
            for (int e = 0; e < count; e++)
            {
                Numbers numbers = generator_server.Numbers;
                Tuple<int, Numbers> d_ns = numbers.GetNextDecimalDigitAndNumbers();
                int dd = d_ns.Item1;
                generator_server.Numbers = d_ns.Item2;
                result_number = result_number + new LongDecimal(dd).Shift(e);
            }
            return result_number.Print();
        }
        private Tuple<int, Numbers> NextDigitAndNumbers(Numbers numbers)
        {
            return numbers.GetNextDecimalDigitAndNumbers();
        }

NumbersServer クラスの Numbers プロパティの get は以下のように generator_server.MoveNext() を実行するようにします。以前これは必要ないと書きましたが、間違っていました。これがないと MoveNext が最初の1回しか実行されないことになってしまいます。

        public Numbers Numbers
        {
            get
            {
                generator_server.MoveNext();
                return generator_server.Current;
            }
            set
            {
                current_numbers = value;
            }