[過去ログ] プログラミングのお題スレ Part13 (1002レス)
前次1-
抽出解除 レス栞

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
リロード規制です。10分ほどで解除するので、他のブラウザへ避難してください。
42
(2): 2019/02/05(火)12:28 ID:aE6b0ZPr(1)調 AAS
>>35 結局 整数のsqrt を作って、範囲の中に納まる最小最大の整数のsqrt を取り出し、その差(+1)がその範囲の中にある平方数の個数と言う作りにした。
ポイントとなった整数のsqrt が秀逸だったのでここに書いておく。 どんなに巨大な数字でも数回のシフト操作だけで終わるから極端にスピードが速い。
ソースは、gist.github.com/bnlucas/5879594

# integer square root
def isqrt_2(n):
 if n < 0:
  raise ValueError('Square root is not defined for negative numbers.')
 x = int(n)
 if x == 0:
  return 0
 a, b = divmod(x.bit_length(), 2)
#divmod(a, b)は(a // b, a % b)のタプルを返す。
#平方数は半分のビット数以下だからそれを最大値で計算開始
 n = 2 ** (a + b)
 while True:
  y = (n + x // n) >> 1 #1bit右にシフト
  if y >= n:
   return n
  n = y

-----------------
#結果 0.0 秒 count= 1000000000
#範囲   999999999000000000000000000000000000 1000000001000000000000000000000000000
#入力bit_length()=120 入力bit_length()=120
平方数範囲 999999999500000000 1000000000499999999
上の二乗  999999999000000000250000000000000000 1000000000999999998249999999000000001
45
(2): 2019/02/05(火)18:45 ID:63VtM8MC(1)調 AAS
>>42 の isqrt_2 を使ったパフォーマンステスト。
次のようなのを継ぎ足してテストした。 例によってインデント部は全角空白に変換してるから、逆変換しないと動かない。

def isSqrt(n):
 return n == isqrt_2(n)**2

v0 = 12345678901234567890
v = v0**2 # 整数平方される対象の数値
loopc = 100000 # をこの回数繰り返す。

isqr=0
start =time.process_time()
for i in range(loopc): isqr=isqrt_2(v)
end =time.process_time()

print('#整数平方(v)の結果',end-start,'秒')
print(' 繰返し数の回数',loopc),print(),print('#v0   ',v0)
print('#v=v0**2=',v),
print('#isqrt(v)',isqr)
print('#上の**2',isqr**2)
print('対象数vのビット数',v.bit_length(),'bit')
print('vが平方数かどうかの判定',isSqrt(v))
-----
#整数平方(v)の結果 0.22398700000002236 秒
繰返し数の回数 100000

#v0    12345678901234567890
#v=v0**2= 152415787532388367501905199875019052100
#isqrt(v) 12345678901234567890
#上の**2 152415787532388367501905199875019052100
対象数vのビット数 127 bit
vが平方数かどうかの判定 True
47: 2019/02/06(水)16:53 ID:XOfzhWu4(1)調 AAS
Wikipediaに Integer square root
https://en.wikipedia.org/wiki/Integer_square_root
があり、その中の 2.1 Using bitwise operations
の二つを試してみたが、
最初のrecursive call を使った方が 1.65秒
次の方が 2.05秒

早いことは早いが、>>42 >>45 のビットシフト法の方がかなり早い。
0.22秒
gmpのisqrt は早そうだが Pythonistaでは使えないので試していない。
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.040s