计算有理数的p-adic范数


11

计算有理数的p-adic范数

编写一个函数或程序,该函数或程序将3个整数m,n,p(其中p是一个正质数)作为输入,然后将p-adic范数(由表示|m/n|_p)输出为(完全归约)分数。众所周知,费马特的边距很小,但未知的是他的电脑屏幕很小。因此,请尝试使代码尽可能短,以使其适合Fermat的屏幕!

定义

给定一个质数p,每个分数m/n都可以唯一地写(忽略符号),(a/b)* p^ee整数,p既不除a也不除b。该p进规范m/np^-e。如果分数为0:,则是一种特殊情况|0|_p = 0

输出格式必须为x/y(例如1/3,对于整数10或两者均等10/1,允许为负,对于负数必须有一个前导减号,例如-1/3

细节

程序必须使用stdin / stdout,或者仅由返回有理数或字符串的函数组成。您必须假设输入m/n没有完全减少。您可以假定这p是素数。该程序必须能够处理之间-2^28最大为的整数2^28,并且不应超过10秒。

不允许使用内置的因式分解和素数检查功能,以及内置的基础对话功能和用于计算p-adic评估或规范的内置功能。

示例(从Wikipedia窃取):

x = m/n = 63/550 = 2^-1 * 3^2 * 5^-2 * 7 * 11^-1
|x|_2 = 2
|x|_3 = 1/9
|x|_5 = 25
|x|_7 = 1/7
|x|_11 = 11
|x|_13 = 1

有趣的琐事

(不一定要了解/阅读此挑战,但也许很高兴作为动机来阅读。)

(如果我使用了错误的单词或其他错误,请纠正我,我不习惯用英语来谈论这个问题。)

如果您将有理数视为一个字段,则p-adic范数会得出p-adic度量d_p(a,b) = |a-b|_p。然后,您可以根据该指标完成此字段,这意味着您可以构造一个新字段,其中所有柯西序列都将收敛,这是一个不错的拓扑属性。(例如,有理数没有,而实数有。)这些p-adic数就像您可能已经猜到的那样,在数论中使用了很多。

另一个有趣的结果是Ostrowski定理,该定理基本上说,有理数上的任何绝对值(如下定义)都是以下三个之一:

  • 琐碎的: |x|=0 iff x=0, |x|=1 otherwise
  • 标准(真实): |x| = x if x>=0, |x| = -x if x<0
  • p-adic(如我们所定义)。

绝对值 / 度量只是对我们认为距离的概括。绝对值|.|满足以下条件:

  • |x| >= 0 and |x|=0 if x=0
  • |xy| = |x| |y|
  • |x+y| <= |x|+|y|

请注意,您可以轻松地从绝对值构造度量标准,反之亦然:|x| := d(0,x)d(x,y) := |x-y|,因此如果您可以 / / (在整数域中),它们几乎是相同的。当然,您可以在没有此结构的情况下在更通用的集合上定义指标。


我假设Mathematica的PadicNorm功能也出来了吗?:P
Alex A.

您假设正确/正确。(在此使用哪个?)
更加模糊的2015年

除非“有趣的属性”部分对完成挑战有用,否则我会说最好只是链接到感兴趣的各方的信息。否则会不必要地使职位混乱。
Alex A.

只是要清楚一点,输出应该是这样的|x|_11 = 11,对吧?还是11很好?是否必须处理x=0此案?
Glen O

@GlenO是的,它确实必须处理这种x=0情况,在本示例中,您也可以输出1111/1,但不必打印|x|_11
瑕疵的

Answers:


3

朱莉娅94 80 75字节

f(m,n,p)=(k=gcd(m,n)
g(m)=m%p>0?g(m÷p)p:1
m!=0?print(g(n÷k),/,g(m÷k)):0)

注意:使用换行符代替分号以提高可读性-两种方法都一样。

这非常简单- g(m,n)函数使用递归和restder(%p^n从输入中提取因子mn=1默认情况下,然后p在递归的每个步骤上乘以,这样输出将为p^n。该代码将该代码应用于,n/gcd(m,n)然后m/gcd(m,n)获得适当的表达式。k=gcd(m,n)用于避免计算gcd(m,n)两次,以节省字符。m!=0是处理下列情况的测试x=0

输出的形式N/11/N适当时Np^e


1

J,35 34字节

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:

这是一个二进制动词,它以质数p为左参数,以数组m n为右参数。它总是打印斜杠/,并返回0/1如果m = 0。像这样使用它:

  f =: (,'/'&,)&":/@(%+./)@(]<.^+.|.@])x:
  5 f 63 550
25/1

说明

x:上扩展的精确度转弯,因为我们正在处理非常大的数字。其余代码的工作方式如下:

(,'/'&,)&":/@(%+./)@(]<.^+.|.@])
                        ^         Power: this gives the array p^n p^m
                         +.       Take element-wise GCD with
                           |.@]   the rotated array n m; this gives
                                  the largest powers of p that divide n and m
                      <.          Take element-wise minimum with
                     [            The array m n to handle the m=0 case correctly
              %+./                Divide this array by its GCD to get it to lowest terms
        &":/                      Convert both elements to strings
 ,'/'&,                           Insert the slash '/' between them

0

CJam,42个字节

q~)\_:*g_sW<o@*28#f{{{_@\%}h;}:G~}_~Gf/'/*

这将以输入0的错误(打印0之后)结束。请在CJam解释器中在线尝试。


0

Stax,32 个字节

éE▌ΦΔΘao£╙)ΩuÅI~AAε3∞xC█&½╤%╩▌ïö

运行并调试

应该能够使其更短。Stax对分数的本地支持非常简洁。

ASCII等效项:

hY{y:+y|aEGsG-ys|**}0?}0{^scxHY%Cy/sWd
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.