F# の例(2)
F# もコンストラクターを3個に削減しました。Seq.unfold (iterate に相当)を使っています。
let Align0<'T> (xs: 'T list) (len: int) (z: 'T): 'T list = [ for xd in xs do yield xd for i in xs.Length .. len - 1 do yield z ] let ZipWith0<'T, 'U> (z: 'T) (f: 'T -> 'T -> 'U) (xs: 'T list) (ys: 'T list): 'U list = let xsx = Align0 xs (List.length ys) z let ysx = Align0 ys (List.length xs) z List.map2 f xsx ysx let FoldL0<'T, 'U> (z: 'U) (f: 'U -> 'T -> 'U) (xs: 'T list): 'U = let mutable a = z for x in xs do a <- f a x a let FoldR0<'T, 'U> (z: 'U) (f: 'U -> 'T -> 'U) (xs: 'T list): 'U = FoldL0 z f (List.rev xs) let EqualAndLess (x: int) (y: int): bool * bool = (x = y, x < y) type LongDecimal(numbers: int list) = let mutable decimals_: int list = numbers new() = LongDecimal([]) new(n: int) = LongDecimal([n]) member this.decimals = decimals_ static member CarryStep_ (carry_and_dec: int * LongDecimal) (x: int): int * LongDecimal = let (carry, dec): int * LongDecimal = carry_and_dec let newdec = new LongDecimal([(x + carry) % 10] @ dec.decimals) ((x + carry) / 10, newdec) member this.Decimalize (c: int, leave: bool): LongDecimal = let (carry, dec) = FoldR0 (c, new LongDecimal()) LongDecimal.CarryStep_ this.decimals if leave && carry <> 0 then dec + carry * 10 else dec member this.Shift (e: int): LongDecimal = (new LongDecimal([ for i in 1 .. e -> 0 ] @ this.decimals)) member this.CollectShiftMult (y: LongDecimal): LongDecimal list = [ let mutable e: int = 0 for xd in this.decimals do yield (y * xd).Shift(e) e <- e + 1 ] static member (+) (x: LongDecimal, n: int): LongDecimal = new LongDecimal([(List.head x.decimals) + n] @ List.skip 1 x.decimals) static member (+) (x: LongDecimal, y: LongDecimal): LongDecimal = (new LongDecimal(ZipWith0 0 (fun a b -> a + b) x.decimals y.decimals)).Decimalize(0, true) static member (-) (x: LongDecimal, y: LongDecimal): LongDecimal = let yds = Align0 y.decimals (List.length x.decimals) 0 (new LongDecimal(ZipWith0 0 (fun a b -> a + b) x.decimals (List.map (fun a -> 9 - a) yds))).Decimalize(1, false) static member (*) (x: LongDecimal, xd: int): LongDecimal = new LongDecimal(List.map (fun (yd: int) -> xd * yd) x.decimals) static member (*) (x: LongDecimal, y: LongDecimal): LongDecimal = List.fold (fun a b -> a + b) (new LongDecimal()) (x.CollectShiftMult y) static member LessOrEqual (x: LongDecimal, y: LongDecimal): bool = let equal = List.forall (fun b -> b) (ZipWith0<int, bool> 0 (fun a b -> a = b) x.decimals y.decimals) if equal then false else let get_not_eq (eq, lt) = not eq let (eq, lt) = List.find get_not_eq (ZipWith0 0 EqualAndLess x.decimals y.decimals) lt member this.Print() = let mutable res: string = ""; let mutable count: int = 0; for d in this.decimals do if count = 1 then res <- res + "." res <- res + d.ToString(); count <- count + 1 res type Numbers(number: LongDecimal, square_difference: LongDecimal, scale: int) = let mutable current_digit = 0 let mutable number: LongDecimal = number let mutable square_difference: LongDecimal = square_difference let mutable scale: int = scale member this.CurrentDigit: int = current_digit member this.GetNextDecimalDigit: int = let two: LongDecimal = new LongDecimal(2) current_digit <- -1 for dd = 9 downto 0 do if current_digit < 0 then let zd: LongDecimal = (new LongDecimal(dd)).Shift(scale) let number_sq_diff: LongDecimal = number * zd * two + zd * zd if LongDecimal.LessOrEqual (number_sq_diff, square_difference) then number <- number + zd; square_difference <- square_difference - number_sq_diff scale <- scale + 1 current_digit <- dd current_digit type NumbersGenerator() = let GenerateDecimal() = let number: LongDecimal = new LongDecimal() let square_difference: LongDecimal = new LongDecimal(3) let nums: Numbers = new Numbers(number, square_difference, 0) seq { while true do yield nums.GetNextDecimalDigit } let generator = GenerateDecimal().GetEnumerator() member this.GetNextDecimalDigit = let b = generator.MoveNext() generator.Current member this.GenerateDecimal_() = let number: LongDecimal = new LongDecimal() let square_difference: LongDecimal = new LongDecimal(3) let nums: Numbers = new Numbers(number, square_difference, 0) seq { while true do yield nums.GetNextDecimalDigit } type NumbersServer() = let mutable current_numbers: Numbers = new Numbers(new LongDecimal(), new LongDecimal(), 0) let GenerateDecimalServer() = let number: LongDecimal = new LongDecimal() let square_difference: LongDecimal = new LongDecimal(3) current_numbers <- new Numbers(number, square_difference, 0) seq { while true do yield current_numbers } let generator_server = GenerateDecimalServer().GetEnumerator() member this.GetNumbers: Numbers = let b = generator_server.MoveNext() generator_server.Current member this.SetNumbers(numbers: Numbers): unit = current_numbers <- numbers member this.Numbers with get(): Numbers = this.GetNumbers and set(value: Numbers) = this.SetNumbers value member this.GenerateDecimalServer_() = let number: LongDecimal = new LongDecimal() let square_difference: LongDecimal = new LongDecimal(3) current_numbers <- new Numbers(number, square_difference, 0) seq { while true do yield current_numbers } let NextNumbers (numbers: Numbers): (Numbers * Numbers) option = let n = numbers.GetNextDecimalDigit Some (numbers, numbers) type Calc() = let mutable generator: NumbersGenerator = new NumbersGenerator() let mutable generator_server: NumbersServer = new NumbersServer() let mutable result_number: LongDecimal = new LongDecimal() let mutable count: int = 21 member this.RepeatGenerator(): string = for e = 0 to count - 1 do result_number <- result_number + (new LongDecimal(generator.GetNextDecimalDigit)).Shift(e) result_number.Print() member this.RepeatServer(): string = for e = 0 to count - 1 do let numbers: Numbers = generator_server.Numbers let dd: int = numbers.GetNextDecimalDigit generator_server.Numbers <- numbers result_number <- result_number + (new LongDecimal(dd)).Shift(e) result_number.Print() member this.IterateGenerator(): string = let list = Seq.toList (Seq.take (count) (generator.GenerateDecimal_())) (new LongDecimal(list)).Print() member this.IterateServer(): string = let number: LongDecimal = new LongDecimal() let square_difference: LongDecimal = new LongDecimal(3) let init_numbers: Numbers = new Numbers(number, square_difference, 0) let list = Seq.toList (Seq.take (count) (Seq.map (fun (numbers: Numbers) -> numbers.CurrentDigit) (Seq.unfold NextNumbers init_numbers))) (new LongDecimal(list)).Print(); printfn "%s" ((new Calc()).RepeatGenerator()) printfn "%s" ((new Calc()).RepeatServer()) printfn "%s" ((new Calc()).IterateGenerator()) printfn "%s" ((new Calc()).IterateServer())
実行結果
1.73205080756887729352
1.73205080756887729352
1.73205080756887729352
1.73205080756887729352