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

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

人工知能的サーバー対ブラウザー(2)

ChatGPT で調べながら 3 の平方根を求めるプログラムを decimal モジュールを使うように書き直しました。

import decimal

# Decimalコンテキストの設定
decimal.getcontext().prec = 21  # 精度を21桁に設定

def UnfoldL(next, init):
    src = init
    while True:
        dd, src = next(src)
        yield dd

def take_generator(count, seq):
    for e in range(count):
        yield next(seq)

def take(count, seq):
    return list(take_generator(count, seq))

def format_decimal(dec):
    return str(dec[0]) + "." + "".join(map(str, dec[1:]))

class Numbers:
    def __init__(self, number, square_difference, scale):
        self.number = number
        self.square_difference = square_difference
        self.scale = scale
    def Copy(self):
        return Numbers(self.number, self.square_difference, self.scale)
    def GetNextDecimalDigit(self):
        two = decimal.Decimal(2)
        for dd in range(9, -1, -1):
            zd = decimal.Decimal(dd).scaleb(-self.scale)
            number_sq_diff = self.number * zd * two + zd * zd
            if number_sq_diff <= self.square_difference:
                self.number = self.number + zd
                self.square_difference = self.square_difference - number_sq_diff
                self.scale += 1
                return dd
        return 0

class NumbersGenerator:
    def __init__(self):
        self.generator = self.GenerateDecimal()
    def GetNextDecimalDigit(self):
        return next(self.generator)
    def GenerateDecimal(self):
        number = decimal.Decimal(0)
        square_difference = decimal.Decimal(3)
        nums = Numbers(number, square_difference, 0)
        while True:
            yield nums.GetNextDecimalDigit()

class NumbersServer:
    def __init__(self):
        number = decimal.Decimal(0)
        square_difference = decimal.Decimal(3)
        self.current_numbers = Numbers(number, square_difference, 0)
        self.generator_server = self.GenerateDecimalServer()
    def GetNumbers(self):
        return self.current_numbers
    def SetNumbers(self, numbers):
        self.current_numbers = numbers
    def GenerateDecimalServer(self):
        while True:
            yield self.current_numbers

class Calc:
    def __init__(self):
        self.count = 21
        self.generator = NumbersGenerator()
        self.generator_server = NumbersServer()
        self.result_number = decimal.Decimal(0)
    def RepeatGenerator(self):
        for e in range(self.count):
            zd = decimal.Decimal(self.generator.GetNextDecimalDigit()).scaleb(-e)
            self.result_number = self.result_number + zd
        return str(self.result_number)
    def RepeatServer(self):
        for e in range(self.count):
            numbers = self.generator_server.GetNumbers()
            dd = numbers.GetNextDecimalDigit()
            self.generator_server.SetNumbers(numbers)
            self.result_number = self.result_number + decimal.Decimal(dd).scaleb(-e)
        return str(self.result_number)
    def IterateGenerator(self):
        dec = take(self.count, self.generator.GenerateDecimal())
        return format_decimal(dec)
    def IterateServer(self):
        number = decimal.Decimal(0)
        square_difference = decimal.Decimal(3)
        init_numbers = Numbers(number, square_difference, 0)
        dec = take(self.count, UnfoldL(NextDigitAndNumbers, init_numbers))
        return format_decimal(dec)

def NextDigitAndNumbers(numbers):
    numbers_copy = numbers.Copy()
    dd = numbers_copy.GetNextDecimalDigit()
    return dd, numbers_copy

print(Calc().RepeatGenerator())
print(Calc().RepeatServer())
print(Calc().IterateGenerator())
print(Calc().IterateServer())
結果

1.73205080756887729352
1.73205080756887729352
1.73205080756887729352
1.73205080756887729352

説明

Numbers クラス

「Numbers 」というよくわからない名前になっていますが、次の桁を計算するための情報です。

NumbersGenerator クラス

サーバー側で次の桁を計算するときのサーバー側を表すクラスです。実際にはイテレーターとして実装されています。

NumbersServer クラス

ユーザーが次の桁を計算するときのサーバー側を表すクラスです。実際にはイテレーターとして実装されています。

Calc().RepeatGenerator()

ユーザーはサーバーで計算された次の桁を受け取るだけという動作を、イテレーターで表したものです。

Calc().RepeatServer()

ユーザーはサーバーから情報を受け取り、ユーザーが次の桁を計算してサーバーに送るという動作を、イテレーターで表したものです。

このときのユーザーの操作をサーバーに伝えることによって、サーバーで計算することができるようになる、というのが言いたいことです。

Calc().IterateGenerator()

ユーザーはサーバーで計算された次の桁を受け取るだけという動作をまとめたものです。