# 小知識:計算π的其中一個方法是,隨機的向一個邊長為n的正方形中撒豆子,
# 然后看這些豆子是否在以n為半徑的四分之一圓內,正方形面積:n*n,四分之一圓的面積:π*n*n/4
# 因此落在四分之一圓內的概率為π/4,這樣我們就能算出π的值,
# 我們這個程式是來講述zmq發布-訂閱程序的流程,
# 通過計算π值為例子來進行計算,
# 首先發布者bitsource隨機生成一個字串,字串偶數位為縱坐標,奇數位為橫坐標,
# 一個字串表示一個點,將奇數位轉換為橫坐標,將偶數位轉換為縱坐標,然后通過計算
# 這個點到原點的距離,來判斷是否為以半徑為B的圓內,通過大量的模擬,來進行計算π,
import random, threading, time, zmq
B = 32 # number of bits of precision in each random integer
def ones_and_zeros(digits):
"""Express `n` in at least `d` binary digits, with no special prefix."""
# getrandbits()
# 方法回傳指定大小(以位為單位)的整數,
return bin(random.getrandbits(digits)).lstrip('0b').zfill(digits)
# 發布者
def bitsource(zcontext, url):
# 發布訂閱函式,發布者,
"""Produce random points in the unit square."""
# 創造一個物件,發布者物件
zsock = zcontext.socket(zmq.PUB)
# 系結URL
zsock.bind(url)
while True:
# 持續不斷的一直發送這里是32位的二進制字符,
# 這里一個字串代表一個點,
zsock.send_string(ones_and_zeros(B * 2))
# 停頓0.01秒,
time.sleep(0.01)
# 訂閱者1
def always_yes(zcontext, in_url, out_url):
"""Coordinates in the lower-left quadrant are inside the unit circle."""
# 創造一個訂閱者物件,
isock = zcontext.socket(zmq.SUB)
# 連接發布者的URL
isock.connect(in_url)
# 設定過濾條件,接收00開頭的
# 如果開頭為00的話,那么這個點x、y值都不會超過半徑的一半
# 一定在四分之一圓內,
isock.setsockopt(zmq.SUBSCRIBE, b'00')
# 推送,
osock = zcontext.socket(zmq.PUSH)
# 連接接收推送的URL
osock.connect(out_url)
while True:
# 接收訂閱者的訊息,
isock.recv_string()
# 推送給發布者訊息,因此我們這里直接發送Y
osock.send_string('Y')
# 訂閱者2
def judge(zcontext, in_url, pythagoras_url, out_url):
"""Determine whether each input coordinate is inside the unit circle."""
# # 創造一個訂閱者物件,
isock = zcontext.socket(zmq.SUB)
# 連接URL
isock.connect(in_url)
# 設定接收訂閱的過濾條件,
for prefix in b'01', b'10', b'11':
isock.setsockopt(zmq.SUBSCRIBE, prefix)
# 設定一個回應物件,
psock = zcontext.socket(zmq.REQ)
psock.connect(pythagoras_url)
# 設定一個推送物件,
osock = zcontext.socket(zmq.PUSH)
osock.connect(out_url)
# 這里用了勾股定理,是兩個落在坐標軸上的點,平方和,
unit = 2 ** (B * 2)
# 這里需要計算是否在四分之一圓內,
while True:
# 接收發布者的訊息,
bits = isock.recv_string()
# 提取這個點的x坐標,y坐標,
n, m = int(bits[::2], 2), int(bits[1::2], 2)
# 發送給客戶請求端
psock.send_json((n, m))
# 然后接受客戶請求端發送過來處理過的資料,
sumsquares = psock.recv_json()
# 判斷是否在圓內,
osock.send_string('Y' if sumsquares < unit else 'N')
# 請求端,
def pythagoras(zcontext, url):
"""Return the sum-of-squares of number sequences."""
zsock = zcontext.socket(zmq.REP)
zsock.bind(url)
while True:
# 這里先請求資料,然后將請求的資料進行處理發送出去,
numbers = zsock.recv_json()
zsock.send_json(sum(n * n for n in numbers))
# 匯總,進行計算π的值,
def tally(zcontext, url):
"""Tally how many points fall within the unit circle, and print pi."""
zsock = zcontext.socket(zmq.PULL)
zsock.bind(url)
# 這里是如果接受到一個Y p+4,接受到一個N ,q + 1
# 然后計算比值,這個就是我們算出來的π的值,
p = q = 0
while True:
decision = zsock.recv_string()
q += 1
if decision == 'Y':
p += 4
print(decision, p / q)
# 我們使用多執行緒的方式,上邊的每一個函式開一個執行緒,,
def start_thread(function, *args):
thread = threading.Thread(target=function, args=args)
thread.daemon = True # so you can easily Ctrl-C the whole program
thread.start()
def main(zcontext):
pubsub = 'tcp://127.0.0.1:6700'
reqrep = 'tcp://127.0.0.1:6701'
pushpull = 'tcp://127.0.0.1:6702'
start_thread(bitsource, zcontext, pubsub)
start_thread(always_yes, zcontext, pubsub, pushpull)
start_thread(judge, zcontext, pubsub, reqrep, pushpull)
start_thread(pythagoras, zcontext, reqrep)
start_thread(tally, zcontext, pushpull)
# 這個是主執行緒,主執行緒結束,其他的多執行緒也就要結束,
time.sleep(30)
if __name__ == '__main__':
main(zmq.Context())
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/231752.html
標籤:Python
上一篇:python-時間差值計算
