高精度金属器件


13

背景

对于每个自然数(正整数),都定义了以著名的黄金均值开头的金属均值,并且每个均值是一个无理常数(其具有无限的非重复小数位数)。

对于自然数金属平均值是二次方程的根

根源永远

但是金属平均值通常作为正数根。因此,对于此问题,它将定义为:

对于结果就是著名的黄金比例:


挑战

您的代码应采用2个输入:n和p (顺序一致并不重要)

  • n是一个自然数,表示哪个金属均值
  • p是一个自然数,表示精度的小数位数

您的代码应将第n个金属平均值输出到p个小数位精度。

有效期

如果您的代码适用于从1到65,535的n和p值,则该代码有效。

您必须以以下形式输出小数

digit.s(不带空格)

例如,小数点后9位的黄金均值为

1.618033988

显示最后一位而不四舍五入,因为它将以较长的十进制扩展形式出现。黄金平均值的下一个数字是7,但是示例中的最后8个数字不应四舍五入为9。

十进制数字的数量必须为p,这意味着还必须包含任何结尾的零。

形式的答案

无效-您必须使用十进制扩展名。

您最多可以输出1个换行符和1个尾随换行符。除数字和单点/句号/句点外,您不得输出任何空格或其他任何字符。

得分了

这是标准代码高尔夫:您的得分是代码中的字节数。


排行榜

(使用Martin的页首横幅代码段

Answers:


17

直流电,12

?kdd*4+v+2/p
  • ? 将n和p压入堆栈
  • k 将精度设置为p
  • dd 重复n次(总共3次)
  • * n * n相乘
  • 4+ 加4
  • v 扎根
  • + 加n(堆栈上的最后一个副本)
  • 2/ 除以2
  • p 打印

测试用例:

$ dc -f metalmean.dc <<< "1 9"
1.618033988
$

7
正确的工作工具。
丹尼斯

5
@Dennis必将成为CJam的第一次,几乎是其他时间的三倍;-)
Digital Trauma

2

R,116字节

library(Rmpfr);s=scan();n=mpfr(s[1],1e6);r=(n+(4+n^2)^.5)/2;t=toString(format(r,s[2]+2));cat(substr(t,1,nchar(t)-1))

这将从STDIN读取两个整数并将结果打印到STDOUT。您可以在线尝试

取消+说明:

# Import the Rmpfr library for arbitrary precision floating point arithmetic
library(Rmpfr)

# Read two integers from STDIN
s <- scan()

# Set n equal to the first input as an mpfr object with 1e6 bits of precision
n <- mpfr(s[1], 1e6)

# Compute the result using the basic formula
r <- (n + sqrt(4 + n^2)) / 2

# Get the rounded string representation of r with 1 more digit than necessary
t <- toString(format(r, s[2] + 2))

# Print the result with p unrounded digits
cat(substr(t, 1, nchar(t) - 1))

如果您没有安装该Rmpfr库,则可以install.packages("Rmpfr"),所有梦想都将实现。


1

Mathematica,50个字节

SetAccuracy[Floor[(#+Sqrt[4+#^2])/2,10^-#2],#2+1]&

定义一个按顺序接受n和的匿名函数p。我使用Floor防止取整SetAccuracy,以获取十进制输出。


@不幸的是,我不能使用机器精度数字,因为它们无法处理p>15
2012rcampion 2015年

1

CJam,35个字节

1'el+~1$*_2#2$2#4*+mQ+2/1$md@+s0'.t

首先读取p,然后读取n

CJam解释器中在线尝试。

怎么运行的

我们简单地从问题中计算出n×10 p的公式,得到结果的整数部分和小数部分除以10 p,用小数点前的零填充小数部分以获得p位数字并打印用点分隔的部分。

1'e  e# Push 1 and 'e'.
l+   e# Read a line from STDIN and prepend the 'e'.
~    e# Evaluate. This pushes 10**p (e.g., 1e3 -> 1000) and n.
1$*  e# Copy 10**p and multiply it with n.
_2#  e# Copy n * 10**p and square it.
2$   e# Copy 10**p.
2#4* e# Square and multiply by 4.
+    e# Add (n * 10**p)**2 and 4 * 10**2p.
mQ   e# Push the integer part of the square root.
+2/  e# Add to n * 10**p and divide by 2.
1$md e# Perform modular division by 10**p.
@+s  e# Add 10**p to the fractional part and convert to string. 
0'.t e# Replace the first character ('1') by a dot.

1

Python 2,92字节

当我现在查看答案时,CJam答案似乎使用与此相同的基本方法。它计算出答案n*10**p,然后加上小数点。由于它计算平方根的整数部分的方式,它效率极低(只需加1直到到达平方根)。

n,p=input()
e=10**p;r=0
while(n*n+4)*e*e>r*r:r+=1
s=str((n*e+r-1)/2);print s[:-p]+'.'+s[-p:]

1

PHP,85 78字节

echo bcdiv(bcadd($n=$argv[bcscale($argv[2])],bcsqrt(bcadd(4,bcpow($n,2)))),2);

它使用BC Math数学扩展,在某些系统上无法使用。需要通过指定命令行选项将其包含在编译时--enable-bcmath。它在Windows上始终可用,并且似乎也包含在与OSX捆绑在一起的PHP版本中。

更新

我在他们的注释中应用了@blackhole建议的所有技巧(谢谢!),然后将初始化压缩$n为首次使用(节省了3个字节),现在代码位于上面代码框中的一行中。


@黑洞 确实是85岁。我可能已经读过86(选择范围稍大),但误写了68。立即修复。
axiac 2015年

1
没问题 :)。顺便说一下,您可以少1个字节:删除括号echo,然后在其后留一个空格。
Blackhole,2015年

1
并且由于您希望bcscale返回true,所以您可以使用$n=$argv[bcscale($argv[2])];并保存另外2个字节。
Blackhole,2015年

这是一个不错的技巧。
axiac 2015年

代码肮脏是一门艺术:P。哦,最后一个:bcpow($n,2)不是为bcmul($n,$n)您节省1个字节。
黑洞

1

J,27字节

4 :'}:":!.(2+x)-:y+%:4+*:y'

说明:

4 :'                      '   | Define an explicit dyad
                       *:y    | Square y
                     4+       | Add 4
                   %:         | Square root
                 y+           | Add y
               -:             | Half
      ":!.(2+x)               | Set print precision to 2+x
    }:                        | Remove last digit, to fix rounding

这样称呼它:

    9 (4 :'}:":!.(2+x)-:y+%:4+*:y') 1
1.618033988

另一个稍微凉一点的解决方案:

4 :'}:":!.(2+x){.>{:p._1,1,~-y'

它可以计算多项式x ^ 2-nx-1的根。不幸的是,J格式化结果的方式使返回所需根的时间略长。

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.