找回密码
 欢迎注册
楼主: 无心人

[讨论] 素性测试中的平方数判定问题

[复制链接]
发表于 2019-10-9 09:33:37 | 显示全部楼层
gxqcn 发表于 2019-10-8 17:12
借题,问一下,可有此类算法:可快速判定一个大整数,有/无 含非 1 的平方因子?

不知道你为什么会死磕这个问题,

Rabin-Miller 强伪素数可能含平方因子吗?
https://bbs.emath.ac.cn/thread-3710-1-1.html

我在下面已经回复你了

https://oeis.org/A001220
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2019-10-9 09:34:37 | 显示全部楼层
gxqcn 发表于 2019-10-8 17:12
借题,问一下,可有此类算法:可快速判定一个大整数,有/无 含非 1 的平方因子?

不要死磕任何数论问题,很难的,
你就测试一下1093 3511这两个数就可以了
计算一下与1093*3511=3837523的最大公约数是否等于1
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2019-10-9 11:10:41 | 显示全部楼层
mathematica 发表于 2019-10-9 09:34
不要死磕任何数论问题,很难的,
你就测试一下1093 3511这两个数就可以了
计算一下与1093*3511=3837523 ...


数学上并没有证明除了这两个数,没有其他例子
另外,Frobenius测试只需要不是平方数,含平方因子的没问题
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2019-10-9 15:18:19 | 显示全部楼层
贴个从Henri Cohen的A Course in Computational Algebraic Number Theory扒下来的平方数检测算法
1、预计算表
for k = 0 to 10
    q11[k] = 0
for k = 0 to 5
    q11[k^2 mod 11] = 1

for k = 0 to 62
    q63[k] = 0
for k = 0 to 31
    q63[k^2 mod 63] = 1

for k = 0 to 63
    q64[k] = 0
for k = 0 to 31
    q64[k^2 mod 64] = 1

for k = 0 to 64
    q65[k] = 0
for k = 0 to 32
    q65[k^2 mod 65] = 1

2、测试
1)、t = n mod 64
    if q64[t] = 0 return n not square number, terminate
    r = n mod 45045
2)、if q63[r mod 63] = 0 return n not square number, terminate
3)、if q65[r mod 65] = 0 return n not square number, terminate
4)、if q11[r mod 11] = 0 return n not square number, terminate
5)、q = sqrt(n), if q^2 != n return n not square number, terminate
return n is square number
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2019-10-9 15:41:46 | 显示全部楼层

  1. function isSquareOrDivBy2357(n)
  2.     if gcd(n, 840) != 1
  3.         return true
  4.     end
  5.     t = n % 840
  6.     if t in [1, 121, 169, 289, 361, 529]
  7.         sq = isqrt(n)
  8.         return sq * sq == n
  9.     else
  10.         return false
  11.     end
  12. end

  13. function isSquare1(n)
  14.     sq = isqrt(n)
  15.     return sq * sq == n
  16. end

  17. q11 =  [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0]
  18. q63 =  [1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0,
  19.         0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
  20.         1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0,
  21.         0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,
  22.         0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0,
  23.         0, 0, 0, 1, 0, 0, 0, 0]
  24. q64 =  [1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
  25.         0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
  26.         0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  27.         1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
  28.         0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
  29.         0, 0, 1, 0, 0, 0, 0, 0, 0]
  30. q65 =  [1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
  31.         0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
  32.         0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
  33.         0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0,
  34.         0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
  35.         1, 1, 0, 0, 0, 0, 1, 0, 0, 1]

  36. function isSquare2(n)
  37.     if q64[n % 64 + 1] == 0
  38.         return false
  39.     end
  40.     r = n % 45045
  41.     if q63[r % 63 + 1] == 0
  42.         return false
  43.     end
  44.     if q65[r % 65 + 1] == 0
  45.         return false
  46.     end
  47.     if q11[r % 11 + 1] == 0
  48.         return false
  49.     end
  50.     sq = isqrt(n)
  51.     return sq * sq == n
  52. end

  53. base = big(10)^16384
  54. test = []
  55. for i in range(0, stop = 65535)
  56.     push!(test, base + i)
  57. end

  58. global cnt = 0
  59. println("1")
  60. @time for t in test
  61.     if isSquareOrDivBy2357(t)
  62.         global cnt += 1
  63.     end
  64. end
  65. println(cnt)

  66. global cnt = 0
  67. println("2")
  68. @time for t in test
  69.     if isSquare1(t)
  70.         global cnt += 1
  71.     end
  72. end
  73. println(cnt)

  74. global cnt = 0
  75. println("3")
  76. @time for t in test
  77.     if isSquare2(t)
  78.         global cnt += 1
  79.     end
  80. end
  81. println(cnt)
复制代码


1
  0.361999 seconds (1.33 M allocations: 33.778 MiB, 10.00% gc time)
50556

2
  6.500475 seconds (590.98 k allocations: 647.587 MiB, 1.93% gc time)
1

3
  0.529858 seconds (1.51 M allocations: 41.500 MiB, 5.29% gc time)
1
测试表明当待测试数较小时,直接开平方的时间最少,Cohen的方法最差
当待测试数字很大时候(大约大于10^1024),我提到的方法较好,但是不能反应实际的平方数,Cohen的其次,直接开平方则较差
所以推荐Cohen的平方测试算法

点评

这个可以,但是具体的界限,估计跟软硬件环境和编程语言有很大关系吧,不好限定  发表于 2019-10-10 10:11
可以先判断数据的大小(比特数),比特大小采用不同的策略  发表于 2019-10-9 16:55
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2019-10-11 14:53:12 | 显示全部楼层
无心人 发表于 2019-10-9 11:10
数学上并没有证明除了这两个数,没有其他例子
另外,Frobenius测试只需要不是平方数,含平方因子的没 ...

难道你的Frobenius测试就能排除所有的合数?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2019-10-13 08:47:57 | 显示全部楼层
mathematica 发表于 2019-10-11 14:53
难道你的Frobenius测试就能排除所有的合数?


欢迎你找到反例
你就用简单形式找到就行:
\(  (1+\sqrt{c})^n \equiv (1 - \sqrt{c})  \mod n, (\frac{c}{n}) = -1 \)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-5-6 15:38 , Processed in 0.050123 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表