多项式插值


12

编写一个 使用真正的任意精度有理数执行多项式插值的程序。输入看起来像这样:

f(1)= 2/3
f(2)= 4/5
f(3)= 6/7
...

您可以假设=符号前后只有一个空格,所有数字都是小数或整数。您可能还假设输入中的所有分数都是不可约的。

您可以假设不需要进行错误检查,即输入是有效的,并且f(x)中没有x被加倍。

输出应采用兼容LaTeX的形式,发出的LaTeX代码应产生与此处给出的输出相同的图形表示。

f(x)= 123x ^ 2 + \ frac {45} {2} x + \ frac {7} {4}

例如,必须尽可能减少分数。\frac{2}{4} 不允许这样的事情。如果数字是整数,请不要使用小数。

特殊规则:

您的程序应该...

  • 适用于12级以下的多项式
  • 不到1分钟即可完成输入
  • 不使用任何为您完成整个计算的函数
  • 输出最小可能次数的多项式

测试用例:

给定的测试用例只是为了澄清。您的程序应为所有正确的输入产生正确的结果。

输入值

f(1)= 2/3
f(2)= 4/5
f(3)= 6/7

输出量

f(x)=-\ frac {4} {105} x ^ 2
       + \ frac {26} {105} x
       + \ frac {16} {35}

输入值

f(-12)= 13/2
f(5/3)= 3/5
f(13)= -6
f(1/5)= -3/4

输出量

f(x)=-\ frac {2186133} {239455744} x ^ 3
       + \ frac {2741731} {149659840} x ^ 2
       + \ frac {26720517} {29201920} x
       -\ frac {279464297} {299319680}

输入值

f(4/3)= 617/81
f(2)= 20/3
f(-8/3)= 6749/81
f(-5)= 7367/12
f(0)= 23/3

输出量

f(x)= \ frac {1} {2} x ^ 4
     -2x ^ 3
     + \ frac {7} {4} x ^ 2
     + \ frac {23} {3}

输入值

f(0)= 5
f(1)= 7
f(2)= 9
f(3)= 11
f(4)= 13

输出量

f(x)= 2x
     + 5

输入值

f(1/2)= -1/2
f(-25)= -1/2
f(-54/12)= -1/2

输出量

f(x)=-\ frac {1} {2}

如果您只使用有理数,为什么还要谈论实数?
乔伊(Joey)

抱歉。我的英语很差。是的,只能使用有理数。结果必须准确。
FUZxxl 2011年

在第一个测试用例中,点(...)是否真的是输入的一部分?
Eelvex

@Eelvex:不。固定。
FUZxxl 2011年

第三个测试用例的输出错误。正确的答案是-\frac{37745}{14592}x^4 - \frac{853249}{43776}x^3 + \frac{57809}{7296}x^2 + \frac{225205}{2736}x + \frac{23}{3}。我怀疑输入的意图是不同的:)
Timwi

Answers:


3

J + sh

J脚本:

i=:0".(1!:1)3
i=:((-:#i),2)$i
c=:|.(%.(x:((i.#i)^~])"0({."1 i)))(+/ .*)(|:{:"1 i)
(":(-.0=c)#(c,.i.-#c))(1!:2)2

sh脚本:

echo -n 'f(x) = '
tr -d 'f()=' | tr /\\n- r' '_  | ./polyint.ijs | sed -e 's/^/+/;s/_/-/;s/\([0-9]*\)r\([0-9]*\)/\\frac{\1}{\2}/;s/ \([0-9]*$\)/x^\1/;s/\^1//;s/x^0//;s/+\(.*-.*\)/\1/'

运行sh脚本:

./pol-int.sh
f(1/2) = -1/2
f(-25) = -1/2
f(-54/12) = -1/2

f(x) = -\frac{1}{2}

./pol-int.sh
f(4/3) = 617/8
f(2) = 20/3
f(-8/3) = 6749/81
f(-5) = 7367/12
f(0) = 23/3

f(x) = -\frac{37745}{14592}x^4
       -\frac{853249}{43776}x^3
     +  \frac{57809}{7296}x^2
     + \frac{225205}{2736}x
     +  \frac{23}{3}

您不必创建完全相同的源代码格式。在LaTeX输出中。通过LaTeX运行后,它应该只产生相同的图形表示。随时保存一些字符。
FUZxxl

我看不懂J,但是从短的长度来看,这意味着J具有矩阵梯形形式的内置功能吗?
Timwi

@Timwi:不,但是我使用内置的“逆矩阵”。J非常简洁:即使我要实现“求逆矩阵”,它也会有几个字符长。
Eelvex

3

Perl(569个字符)

use Math'BigInt;sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}sub c{new Math'BigInt$_[0]}$a=@c=<>;for(@c){m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;$j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;$j{$a,$i}=c$3;$k{$a,$i++}=c$4||1}for$p(0..$a-1){for$y(0..$p-1,$p+1..$a-1){$n=$j{$p,$y}*$k{$p,$p};$o=$k{$p,$y}*$j{$p,$p};$j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,$k{$_,$y}*=$k{$_,$p}*$o for 0..$a}}print"f(x)=";for(1..$a){$s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};$u=abs$t,print$t>0?"$z":'-',($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p if$t/=$s}

详细说明:

use Math'BigInt;

# Subroutine to calculate gcd of two numbers
sub r{($u,$v)=@_;$v?r($v,$u%$v):$u}

# Subroutine to create BigInts
sub c{new Math'BigInt$_[0]}

# Read input
# Throughout, $a is the number of equations.
$a=@c=<>;

# Initialises the $a+1 × $a matrix with all the values.
# $j{$x,$y} contains the numerator, $k{$x,$y} the denominator.
for(@c)
{
    m!(-?\d+)/?(\d*). = (-?\d+)/?(\d*)!;

    # Puzzle for the reader: why is $i|=0 in the second one,
    # not the first one? Answer at the bottom!
    $j{$_,$i}=$1**c$_,$k{$_,$i|=0}=($2||1)**c$_ for 0..$a;
    $j{$a,$i}=c$3;
    $k{$a,$i++}=c$4||1
}

# Generates the matrix echelon form.
# Basically, it works like this:
for$p(0..$a-1)
{
    # For each element along the diagonal {$p,$p}, set all the values above and
    # below it to 0 by adding a multiple of row $p to each of the other rows.
    for$y(0..$p-1,$p+1..$a-1)
    {
        # So we need to multiply the row $p by the value of {$p,$y}/{$p,$p}
        # (stored in $n/$o) and then subtract that from row $y.
        $n=$j{$p,$y}*$k{$p,$p};
        $o=$k{$p,$y}*$j{$p,$p};
            $j{$_,$y}=$j{$_,$y}*$k{$_,$p}*$o-$k{$_,$y}*$j{$_,$p}*$n,
            $k{$_,$y}*=$k{$_,$p}*$o
        for 0..$a
    }
}

# Outputs the result
print"f(x)=";
for(1..$a)
{
    # Note this sets $p = $a-$_. $p is the power of x.
    # We need to divide {$a,$p} by {$p,$p}. Store the result in $t/$w.
    # We also need to put the fraction in lowest terms, so calculate the gcd.
    $s=r$t=$j{$a,$p=$a-$_}*$k{$p,$p},$w=$k{$a,$p}*$j{$p,$p};

    # Output this term only if the numerator ($t) is non-zero.
    # Output a plus sign only if this isn’t the first term.
    # Output a fraction only if the denomator ($w) isn’t 1.
        $u=abs$t,print$t>0?"$z":'-',
        ($z='+',$w/=$s)-1?"\\frac{$u}{$w}":$u,$p>1?"x^$p":x x$p
    if$t/=$s
}

# Answer to the puzzle buried in the code above:
# It’s because the second part is passed as a second argument to c,
# hence it is evaluated before the first part.

评论

  • 我确定有一个矩阵处理模块,可以提供梯形形式的功能。我特别不使用它(甚至没有搜索一个),因为我认为这是自己做这个竞赛的目的。这样更有趣。当然,关于BigInt也可以这样说,但是我怀疑没有人会尝试这种挑战。

编辑

  • (630→585)意识到我可以在一个循环中而不是两个循环中执行梯形表格。在代码中添加解释作为注释。

  • (585→583)刚刚发现了让我'代替使用的软件包语法::

  • (583→573)再打高尔夫球

  • (573→569)较短的正则表达式可解析输入


我不断收到编译错误:ideone.com/LoB2T
FUZxxl

@FUZxxl:感谢您指出这一点。只是缺少一个空间。立即修复。
Timwi

3

TI-Basic(83/84):109个字符

从技术上讲,TI-Basic的字符数为109个,将dim(,For(,->​​,rref(,[A])计数为“一个字符”。

输入以(x,y)对的形式格式化为L1和L2 [ex L1 =(1,2,3,4),L2 =(2,3,5,7)]。

{1,1}->dim([A]
{dim(L1),dim(L2)+1}->dim([A]
For(A,1,dim(L1)
For(B,dim(L1)-1,0,-1
L1(A)^B->[A](A,dim(L1)-B
End
L2(A->[A](A,dim(L1)+1
End
rref([A]->[A]
{0}->L3
For(A,1,dim(L1)
[A](A,dim(L1)+1->L3(A
End
Disp L3

1
这不使用基本原理或LaTeX形式。
lirtosiast,2015年

1

Lagrange方法,Python,199字节

有点晚了,但是...

def lagrange(dp):
l = lambda i: lambda x: (prod([(x - dp[j][0]) / (dp[i][0] - dp[j][0]) for j in range(len(dp)) if i != j]))
return lambda x: sum([l(i)(x) * dp[i][1] for i in range(len(dp))])

1
您可能不需要运算符周围的所有空格,是吗?

0
l=lambda D,i:lambda x:prod((x-Dj[0])/(D[i][0]-Dj[0])for j,Dj in enumerate(D)if i!=j)
L=lambda D:lambda x:sum(l(D,i)(x)*Di[1]for i,Di in enumerate(D))

只是Fred Freys代码的简化版本。注意,可能会跳过将D传递给l的情况,因为它可以将其从外部范围中拉出来。正如您可能在这里对i进行的操作一样,我们甚至可以剃掉一个λ。我有一天会测试。

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.