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()
ユーザーはサーバーで計算された次の桁を受け取るだけという動作をまとめたものです。
Calc().IterateServer()
ユーザーはサーバーから情報を受け取り、ユーザーが次の桁を計算してサーバーに送るという動作をまとめたものです。これはサーバーは何もすることがなくなるので何もしていません。





![[第3版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践 impress top gearシリーズ [第3版]Python機械学習プログラミング 達人データサイエンティストによる理論と実践 impress top gearシリーズ](https://m.media-amazon.com/images/I/514u2pGsJNL._SL500_.jpg)