互素数和pi


23

介绍

数论以意想不到的联系的形式充满了奇迹。这是其中之一。

如果两个整数除1以外没有其他共同因数,则它们是互质的。给定数N,请考虑从1到N的所有整数。随机抽取两个这样的整数(所有整数在每次抽取时被选择的可能性相同;抽取是独立的且具有替换值)。令p表示两个选定整数互质的概率。然后p趋于6 / π 2 ≈0.6079 ...作为Ñ趋于无穷大。

挑战

这一挑战的目的是将p作为N的函数进行计算。

例如,考虑N =4。从整数1,2,3,4获得16对可能。这些对中的11个是互质的,即(1,1),(1,2),(1,3),(1,4),(2,1),(3,1),(4,1 ),(2,3),(3,2),(3,4),(4,3)。因此,对于N = 4,p为11/16 = 0.6875 。

p确切值至少需要用四个小数点来计算。这意味着计算必须是确定性的(与蒙特卡洛相对)。但这不必是上面所有对的直接枚举;可以使用任何方法。

可以使用函数参数或stdin / stdout。如果显示输出,则可以省略尾随零。因此例如0.6300可以显示为0.63。它应显示为十进制数字,而不是分数(63/100不允许显示字符串)。

获胜标准是最少的字节。内置函数的使用没有限制。

测试用例

输入/输出(如上所述,只有四个小数是必需的):

1    / 1.000000000000000
2    / 0.750000000000000
4    / 0.687500000000000
10   / 0.630000000000000
100  / 0.608700000000000
1000 / 0.608383000000000

输入范围有界限吗?
Eric Towers 2015年

@EricTowers该程序应可在任何合理的大小下运行,直到内存和数据类型的限制。至少1000
Luis Mendo 2015年

是否允许使用有理数作为返回值(而不是字符串)?我的语言具有本地有理类型,其中63/100是有效的文字,可用于计算。(我正在谈论的语言:FactorRacket
cat

@cat当然,继续!不过请考虑到所需的精度
Luis Mendo

Answers:


14

果冻12 8字节

RÆṪSḤ’÷²

在线尝试!

以下二进制代码与此版本的Jelly解释器一起使用

0000000: 52 91 b0 53 aa b7 9a 8a  R..S....

理念

显然,对的数量(J,K) ,使得Ĵ≤ķĴķ是互质数等于对数(K,J)满足同样的条件。另外,如果j = k,则j = 1 = k

因此,要计算坐标在1n之间的互质对的数量,只要计算对(j,k)的对m的数量即可使j≤k,然后计算2m-1

最后,由于欧拉的上位函数φ(k)得出介于1k之间的,与k互质的整数,我们可以将m计算为φ(1)+…+φ(n)

RÆṪSḤ’÷²    Input: n

R           Yield [1, ..., n].
 ÆṪ         Apply Euler's totient function to each k in [1, ..., n].
   S        Compute the sum of all results.
    Ḥ       Multiply the result by 2.
     ’      Subtract 1.
      ÷²    Divide the result by n².

2
哦,果冻包含了totient功能!?好主意!
Luis Mendo 2015年

2
倒数计时,直到MATL在T-1天包括一名总指挥...
quintopia

@quintopia(我终于包括了totient函数):
Luis

14

Mathematica 43 42字节

我发现 从原点可见的莱迪思点,从中拍摄下图,可以通过以下有关单位晶格给定正方形区域的问题来帮助重新定义问题:

  • 多少个晶格点具有互质坐标?
  • 从原点可以看到多少单位晶格点?

grid


N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&

例子

尾随零被省略。

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&/@Range@10

{1.,0.75,0.777778,0.6875,0.76,0.638889,0.714286,0.671875,0.679012,0.63}


定时

时间以秒为单位,位于答案之前。

N@Mean[Mean/@Boole@Array[CoprimeQ,{#,#}]]&[1000]// AbsoluteTiming

{0.605571,0.608383}



6

Mathematica,42 32字节

Count[GCD~Array~{#,#},1,2]/#^2.&

匿名函数,使用简单的蛮力。最后一种情况在我的计算机上运行大约0.37秒。说明:

                               &   A function taking N and returning
Count[               , , ]           the number of
                      1               ones
                                     in the
                        2             second
                                     level of
         ~Array~                      a matrix of
      GCD                              the greatest common denominators of
                {#,#}                 all 2-tuples in [1..N]
                          /         divided by
                           #          N
                            ^2.      squared.

您可以为我们中那些没有Mathematica的人发布示例跑步和说明吗?
路易斯·门多

2
这将统一我们的意见: Count[Array[GCD,{#, #}],1,2]/#^2.& 请成为我的客人。
DavidC

4

Dyalog APL,15个字节

(+/÷⍴)∘∊1=⍳∘.∨⍳

非常简单。这是单子功能火车。Iota是从1到输入的数字,因此我们将外部乘积乘以gcd,然后计算一个的比例。


3

八度,49 47字节

只需计算gcd所有货币对并进行计数。

@(n)mean(mean(gcd(c=kron(ones(n,1),1:n),c')<2))

Kronecker产品很棒。


kron!好主意!
路易斯·门多

我首先使用meshgrid,但是后来我发现可以使用kroninline 做同样的事情!(->匿名函数)
漏洞

2

JavaScript(ES6),88个字节

n=>eval(`p=0;for(i=n;i;i--)for(j=n;j;j--,p+=a)for(a=1,k=j;k>1;k--)a=i%k||j%k?a:0;p/n/n`)

说明

n=>
  eval(`                     // use eval to enable for loop without {} or return
    p=0;                     // p = number of pairs
    for(i=n;i;i--)           // i = 1 to n
      for(j=n;j;j--,p+=a)    // j = i to n, a will equal 1 if i and j are coprime, else 0
        for(a=1,k=j;k>1;k--) // for each number from 0 to j
          a=i%k||j%k?a:0;    // if i%k and j%k are both 0, this pair is not coprime
    p/n/n                    // return result (equivalent to p/(n*n))
  `)

测试

需要较长时间(>100)的值n


2

严重的是15个字节

,;ª)u1x`▒`MΣτD/

十六进制转储:

2c3ba62975317860b1604de4e7442f

在线试用

我不会费心地解释它,因为它实际上使用了与Dennis的Jelly解决方案完全相同的算法(尽管我是独立派生的)。


2

J,19 17字节

*:%~1-~5+/@p:|@i:

用法:

   (*:%~1-~5+/@p:|@i:) 4
0.6875

说明:

*:%~1-~5+/@p:|@i:
               i: [-n..n]
             |@   absolute value of each element ([n..1,0,1,..n])
       5+/@p:     sum of the totient function for each element
    1-~           decreased by one, giving the number of co-prime pairs
*:%~              divided by N^2

Dennis的解决方案很好地解释了如何使用totient函数。

在这里在线尝试。


2

Mathematica,35个字节

实现@Dennis的算法。

(2`4Plus@@EulerPhi@Range[#]-1)/#^2&

计算从1到输入值范围内的总和(欧拉phi函数)。乘以浮点数二(精度为四位数),然后减一。(可以通过改用“ 2”和“ 1`4” 来保持更高的精度。)这是互质对的总数,因此除以输入的平方即可得到所需的分数。因为这两个是一个近似数,所以结果也是。

测试(在我们至少有一个人认为这很有趣的情况下,在左列中提供了时序数据),并为其分配了功能,f以便更轻松地读取测试行。

f=(2`4Plus@@EulerPhi@Range[#]-1)/#^2&
RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000}
(* {{5.71*10^-6, 1.000}, 
    {5.98*10^-6, 0.750}, 
    {0.000010  , 0.6875}, 
    {0.0000235 , 0.6300}, 
    {0.00028   , 0.6087}, 
    {0.0033    , 0.6084} }  *)

编辑:显示输入范围的范围(将精度交换为一个而不是两个,因为否则结果将变得单调),并挑战其他人执行相同的操作...

f = (2 Plus @@ EulerPhi@Range[#] - 1`4)/#^2 &
{#}~Join~RepeatedTiming[f[#]] & /@ {1, 2, 4, 10, 100, 1000, 10^4, 10^5, 10^6, 10^7}
(*  Results are {input, wall time, output}
    {{       1,  5.3*10^-6, 1.000}, 
     {       2,  6.0*10^-6, 0.7500}, 
     {       4,  0.0000102, 0.68750}, 
     {      10,  0.000023 , 0.63000}, 
     {     100,  0.00028  , 0.6087000}, 
     {    1000,  0.0035   , 0.608383000}, 
     {   10000,  0.040    , 0.60794971000}, 
     {  100000,  0.438    , 0.6079301507000}, 
     { 1000000,  4.811    , 0.607927104783000}, 
     {10000000, 64.0      , 0.60792712854483000}}  *)

RepeatedTiming[]多次执行计算并取平均时间,尝试忽略冷缓存和其他导致时序异常的影响。渐近极限为

N[6/Pi^2,30]
(*  0.607927101854026628663276779258  *)

因此对于参数> 10 ^ 4,我们只需返回“ 0.6079”即可满足指定的精度和准确性要求。


2

朱莉娅,95个字节

n->(c=combinations([1:n;1:n],2);((L=length)(collect(filter(x->gcd(x...)<2,c)))÷2+1)/L(∪(c)))

现在只是简单的方法;我将尽快研究更短/更优雅的解决方案。这是一个匿名函数,它接受整数并返回浮点数。要调用它,请将其分配给变量。

取消高尔夫:

function f(n::Integer)
    # Get all pairs of the integers from 1 to n
    c = combinations([1:n; 1:n], 2)

    # Get the coprime pairs
    p = filter(x -> gcd(x...) == 1, c)

    # Compute the probability
    return (length(collect(p)) ÷ 2 + 1) / length(unique(c))
end

据我所知,您不需要collect一个懒惰的对象来获取它length

@cat在某些length未定义方法的地方进行处理,对于过滤后的组合迭代器,就是这种情况。类似地,endof这是行不通的,因为没有用于该类型的方法getindex
Alex A.


@cat range与返回的对象类型不同combinations。后者返回组合上的迭代器,该组合是没有定义length方法的单独类型。看这里。(此外,:语法更range适合于构造范围;)
Alex A.

2

Sage,55字节

lambda a:n((sum(map(euler_phi,range(1,a+1)))*2-1)/a**2)

借助Sage象征性地进行所有计算,机器的epsilon和浮点问题不会出现。为了遵循输出格式规则,需要进行权衡,需要另外调用n()(十进制逼近函数)。

在线尝试


非常好!您似乎最近经常使用Sage :-)
Luis Mendo

@LuisMendo Sage很棒,可以做所有事情。在基于数学的挑战中使用它非常好,因为它具有像Mathematica这样的巨大内置库,但是(由于a)不是Mathematica而语法更好(b)基于Python)。
Mego 2016年

2

MATL20 17字节

这使用该语言的当前版本(5.0.0)

基于@flawr的答案的方法

i:tg!X*t!Zd1=Y)Ym

编辑(2015年4月28日)在线试用!发布此答案后,功能Y)重命名为 X:;。该链接包括该更改。

>> matl i:tg!X*t!Zd1=Y)Ym
> 100
0.6087

说明

i:         % vector 1, 2, ... up to input number
tg!        % copy, convert into ones, transpose
X*         % Kronecker product. Produces a matrix
t!         % copy, transpose
Zd         % gcd of all pairs
1=         % is it equal to 1?
Y)         % linearize into column array
Ym         % compute mean

旧答案:20个字节

Oi:t"t@Zd1=sb+w]n2^/

说明

O             % produce literal 0. Initiallizes count of co-prime pairs.
i             % input number, say N
:             % create vector 1, 2, ... N
t             % duplicate of vector
"             % for loop
    t         % duplicate of vector
    @         % loop variable: each element from vector
    Zd        % gcd of vector and loop variable. Produces a vector
    1=s       % number of "1" in result. Each "1" indicates co-primality
    b+w       % accumulate into count of co-prime pairs
]             % end
n2^/          % divide by N^2

像我在八度音阶中使用的方法,您能做得更短吗?
瑕疵的

确实!谢谢!少3个字节。您应该自己在MATL中完成它:-)
Luis Mendo

如果没有超过我的就寝时间,我会尝试的)=
错误的

1

PARI / GP,25个字节

使该函数匿名可以节省一个字节,但随后我必须使用self使其整体更昂贵。

f(n)=n^2-sum(j=2,n,f(n\j))

1

因子, 120个 113字节

我花了很多时间在高尔夫球上,所以我不能再短了。

翻译:朱莉娅

[ [a,b] dup append 2 <combinations> [ members ] keep [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f ]

该示例在前5个测试用例上运行(值1000导致其冻结了编辑器,并且现在我不必费心编译可执行文件):

! with floating point division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap /f 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
! with rational division
IN: scratchpad auto-use {
      1    
      2    
      4    
      10   
      100  
    }
    [ 
      [1,b] dup append 2 <combinations> [ members ] keep 
      [ first2 coprime? ] filter [ length ] bi@ 2 /i 1 + swap / 
    ]
    map

--- Data stack:
{ 1.0 0.75 0.6875 0.63 0.6087 }
{ 1 3/4 11/16 63/100 6087/10000 }

也许添加示例运行?
Luis Mendo

1
@LuisMendo完成了!

1

萨摩(12字节)

免责声明:不参与竞争,因为我在发布问题后更新了语言。

▌;\φΣ2*($2^/

十六进制转储(Samau使用CP737编码):

dd 3b 5c ad 91 32 2a 28 24 32 5e 2f

使用与Dennis在Jelly中的答案相同的算法。


0

Python2 / Pypy,178个字节

x文件中:

N={1:set([1])}
n=0
c=1.0
e=input()
while n<e:
 n+=1
 for d in N[n]:
  m=n+d
  try:N[m].add(d)
  except:N[m]=set([d,m])
 for m in range(1,n):
  if N[m]&N[n]==N[1]:c+=2
print c/n/n

运行:

$ pypy x <<<1
1.0
$ pypy x <<<10
0.63
$ pypy x <<<100
0.6087
$ pypy x <<<1000
0.608383

代码对同质数对进行(n,m) for m<n两次计数(c+=2)。这会忽略(i,i) for i=1..n除之外的其他方法(1,1),因此可以通过初始化计数器进行校正11.0以准备稍后的浮点除法)以进行补偿。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.