制作一个随机数生成器

伪随机数序列是一组数字序列,在偶然的观察者看来是随机的,但它是由确定的、可重复的算法生成的。用于生成伪随机数序列的最简单算法之一是线性同余随机数生成器。这是一个生成整数序列的简单数学公式。为了形成序列,我们选择一个任意整数作为序列的种子。然后,我们将起始值替换为一个简单的线性函数,以生成序列中的下一个数字。最常见的是,简单的线性函数使用两个大素数作为它的系数。

X1 = 12553 x0 + 15401

我们重复这个过程来得到一个完整的数列。如果我们这样做,这个数列通常会趋向正无穷或负无穷。为了防止这种情况,我们在每一轮中对每个数字取一个大质数b的模。

X1 = (12553 x0 + 15401) mod 6133

这保证了数字被困在从0到b-1的范围内。通常,由该过程生成的整数序列不会立即对我们有用,因为,比如说,我们可能对生成从0到c-1范围内的其他整数c感兴趣。这很容易修复。如果c < b,我们可以为生成的每个数字计算x % c,并在生成时保存x % c值的列表。

下面是一个简单的Python示例程序,它使用此过程生成并打印一个0-99范围内的整数列表:

#在(100)范围内n的伪随机序列的种子值:print(x % 100) x = (12553*x+15401)%6133

接下来,我们希望以某种方式封装随机数生成过程,以便我们可以根据需要启动和停止该过程。这样做的关键是将x的当前值放在一个安全的位置,以便我们可以在需要时访问它以生成序列中的下一个x。这是一个很好的Python类概念赢博体育程序。Python类以成员变量的形式存储状态信息。在本例中,我们将创建一个随机序列类,它将x变量的当前值存储为成员变量。接下来,我们还需要为类配备至少一个方法,客户机可以使用该方法从序列中获取新数字。

下面是一个Python类的代码,它可以完成这些事情。

class RndSeq(): def __init__(self,seed = 0): self。x = seed def nextInt(self,N): ““”返回0到N-1范围内的随机整数。”“”如果N > 5000: print("RndSeq。nextInt要求它的参数小于或等于5000 ")返回0 self。X = (12553*self. X +15401)%6133返回self。x % N

这段代码显示了创建一个有用的类所需要的最少的东西。该类包含一个__init__函数,用于初始化对象。在本例中,需要用种子值初始化成员变量x。由于类在成员变量中存储有用的信息,因此还需要成员函数来访问和修改这些值。在本例中,我们只需要一个成员函数nextInt(),它将计算并存储序列中的下一个x,并根据对象中隐藏的x的新值返回结果。

这段代码存储在一个名为“rndseq.py”的文件中。我们可以在一个简单的测试程序中导入和使用这个类。

from rndseq import rndseq seed = input(“为序列输入一个种子值:”)s = rndseq (int(seed)) for n in range(100): print(s. nextint (100))

复数类

对于我们的下一个Python类示例,我将构造一个表示复数的类。这是一个非常简单的类,只有两个数据成员,即数字的实部和虚部。该类包含读取这些数据成员以及计算和返回复数的模数的方法。

因为我们希望能够对复数对象进行算术运算,所以我还为这个类提供了许多操作符重载来实现各种操作。

当您尝试对一对数据项执行操作时,例如添加两个Complex对象,Python将尝试通过将代码转换为类似于方法调用的内容来理解该操作。这里有一个例子。假设我们编写代码

a = Complex(2,3)
b = Complex(3,4)
c = a*b

当Python解释器到达最后一条语句时,它会尝试通过首先将代码转换为另一种形式来理解那里的代码:

C = a.__mul__(b)

这具有将方法调用赢博体育于具有参数b的对象a的形式。为了使其工作,Python将检查存储在a中的对象,以查看它是否具有同名的方法。如果有,它会调用那个方法。

下面是Complex类中__mul__方法的代码。

def __mul__(self,other): r = self.real*other. getreal () - self. image *other. getimag () i = self.real*other. getimag () + self. image *other. getreal () return Complex(r,i)

此方法使用该操作的标准数学规则实现复杂乘法。在计算出产品的实部和虚部之后,该函数构造并返回一个包含这些部分的Complex对象。

在类中提供的另一个方便的方法是__str__方法。当您尝试使用str()将对象转换为文本时,将调用此方法。这里有一个例子。

x = Complex(2,1) print(str(x))

当Python解释器遇到第二条语句时,它将尝试将其重写为

print (x.__str__ ())

如果x是一个对象,并且x所属的类实现了__str__方法,则此操作将成功。

下面是Complex类的__str__方法的代码。

Def __str__(self):如果self。Imag < 0:返回str(self.real)+"-"+str(-self. Imag)+"i" elif self。Imag > 0:返回str(self.real)+"+"+str(self.imag)+"i" else:返回str(self.real)

类的代码

下面是Complex类的完整源代码。这段代码位于一个名为complex.py的独立源文件中。

import math class Complex(): def __init__(self,real,imag = 0): self。真实的自我。imagag = imagdefgetreal (self):返回self。real def (self):返回self。imag def getAbs(self):返回math.sqrt(self.real*self.real+self. image *self. image) def __add__(self,other):返回Complex(self.real+other. getreal (),self. image +other. getimag ()) def __sub__(self,other):返回Complex(self.real-other. getreal (),self. image -other. getimag ()) def __mul__(self,other): r = self.real*other. getreal () - self. image *other. getimag () i = self.real*other. getimag () +self. image *other. getreal()返回Complex(r,i) def __truediv__(self,other):d = other.getReal()*other.getReal() + other.getImag()*other.getImag() r = (self.real*other.getReal() + self. imagag *other.getImag()) / d i = (self. imagag *other.getReal() - self.real*other.getImag()) / d返回Complex(r,i) def __str__(self):如果self。Imag < 0:返回str(self.real)+"-"+str(-self. Imag)+"i" elif self。Imag > 0:返回str(self.real)+"+"+str(self.imag)+"i" else:返回str(self.real)

赢博体育:牛顿复数法

下面是一个利用复数类的赢博体育程序。这个程序是牛顿方法的一个实现,它利用了牛顿方法在复数存在时工作得很好的事实。

这个程序试图找到多项式的根

X4 + 2x3 - 6x2 + 8x + 80

这个多项式没有实根:它的四个根都在复平面上。如果你用一个复数作为开始的猜想来运行这个程序它将收敛于这四个复根之一。如果你用一个实数作为开始的猜测来启动程序,牛顿的方法就会陷入一个无限循环并且不会收敛。当发生这种情况时,您必须通过在IDE中选择stop命令或在终端中按control-C组合键来停止程序。

用牛顿法求出f(x) = x^4 + 2 x^3 - 6 x^2 + 8 x + 80的根。这个多项式有四个复根。定义函数及其导数def (x): return ((x+ complex (2))*x+ complex (-6))*x+ complex (8))*x + complex (80) def fp(x): return ((complex (4)*x+ complex (6))*x+ complex (-12))*x+ complex (8) r = input(“输入您的开始猜测的实部:”)i = input(“输入您的开始猜测的虚部:”)x = complex (float(r),float(i)) y = f(x)公差= 10e-6而y.getAbs() >公差:#计算f'(x) yp = fp(x) #执行一轮牛顿方法x = x - y/yp y = f(x) print(“根估计是”+ str(x))

这里需要注意的重要一点是赢博体育出现在f(x)及其导数定义中的数字都必须是复数。我们需要这样做,因为允许我们对复数对象进行算术运算的运算符函数要求对复数对象进行运算的两个操作数。