力を上げる


12

チャレンジ

課題は、正のaゼロ以外の数を取り、b出力a^b(aの累乗b)を行うプログラムを作成することです。+ - * / abs()数学関数/演算子としてのみ使用できます。これらはスカラー値にのみ適用できますが、リスト全体または配列には適用できません。

例:

1.234 ^ 5.678 = 3.29980
4.5   ^ 4.5   = 869.874
4.5   ^-4.5   = 0.00114959

関連:http : //xkcd.com/217/

詳細

コンソールで使用するための関数または同様の構造を作成できます。コンソール入力を使用できない場合は、両方の数値が標準出力またはファイルへの書き込みを介して変数と出力に保存されていると想定できます。出力は、少なくとも4桁の有効数字に修正する必要があります。両方がゼロでないaと仮定できbます。1分を大幅に超えるランタイムは受け入れられません。最小バイト数が勝ちます。プログラムとアルゴリズムを説明してください。

編集:ポジティブベースのみを考慮する必要があります。あなたが仮定することができa>0ます。両方の数値が整数である必要はないことに注意してください!!!


3
10進数の累乗を要求していますか?言うように、4.5 ^ 4.5?
フアンドン14

1
これは、基数が負の場合、虚数も出力する必要があるということですか?
ベベ14

1
出力は何にすべき-0.5 ** 0.5ですか?
デニス14

OKその場合は考えていませんでした、ありがとう:負のベースを正しく実装してはいけません。@fuandon正確に、実数には小数を含めることができます(少なくともほとんどのプログラミング言語で=)
flawr 14

b <0のテストケースを追加したい: `4.5 ^ -4.5 = 0.0011496 '
edc65 14

回答:


3

Python、77

他のいくつかの回答と同様に、これはlogとexpに基づいています。しかし、関数は、常微分方程式を数値的に解くことによって計算されます。

def f(a,b,y=1):
 if a<1:a=1/a;b=-b
 while a>1:a/=1e-7+1;y*=b*1e-7+1
 return y

要件を満たしていますか?質問の例については、はい。大きなaの場合、非常に長い時間がかかります。aまたはbが大きい場合、不正確になります。

例:

a            b            f(a, b)      pow(a, b)      <1e-5 rel error?
       1.234        5.678       3.2998       3.2998   OK
         4.5          4.5      869.873      869.874   OK
         4.5         -4.5   0.00114959   0.00114959   OK
         0.5          0.5     0.707107     0.707107   OK
         0.5         -0.5      1.41421      1.41421   OK
          80            5  3.27679e+09   3.2768e+09   OK
     2.71828      3.14159      23.1407      23.1407   OK

更新:flawrは数学の詳細を尋ねたので、ここに行きます。次の初期値の問題を検討しました。

  • x '(t)= x(t)、x(0)=1。解はexp(t)です。
  • y '(t)= by(t)、y(0)=1。解はexp(bt)です。

x(t)= aのようなtの値を見つけることができれば、y(t)= exp(bt)= a ^ bになります。初期値の問題を数値的に解く最も簡単な方法は、オイラーの方法です。関数が持つはずの導関数を計算し、導関数の方向にステップを取り、それに比例しますが、小さな定数でスケーリングされます。だからそれは私がやっていることです、xがaと同じくらい大きくなるまで小さなステップを踏んで、その時yが何であるかを見てください。まあ、それは私がそれを考えた方法です。私のコードでは、tは明示的に計算されることはなく(1e-7 * whileループのステップ数)、代わりにaでxの計算を行うことでいくつかの文字を保存しました。


それは素晴らしく見える、私は別の異なるアプローチを見てうれしいです!これらの微分方程式についてもう少し教えてください。私は一般的にそれらが何であるかを知っていますが、プログラムがそれらをどのように使用するかを理解することができませんでした=)
flawr 14

@flawr:わかりました。数学についての詳細を更新しました。
19:34に14

6

JavaScript(E6)155174191

編集2 @bebeが示唆するように、再帰関数を使用します(パフォーマンスは悪化しますが、短くなります)
R関数をわずかに変更して、「過剰な再帰」
テストスイートを追加しました。この関数は、3000未満の基数および範囲-50..50の指数に対して良好に機能します。Golfedをより正確に
編集

任意の実数は有理数で近似できます(実際にはIEEE標準の「実」数は有理数を格納します)。任意の有理数は、aおよびb整数を持つ分数a / bとして表すことができます。x ^(a / b)は(x ^ a)のルートbまたは(xのルートb)^ aです。整数のべき乗は、平方することで非常に簡単です。整数ルートは、数値的手法を使用して近似できます。

コード

P=(x,e)=>(
  f=1e7,e<0&&(x=1/x,e=-e),
  F=(b,e,r=1)=>e?F(b*b,e>>1,e&1?r*b:r):r,
  R=(b,e,g=1,y=1e-30,d=(b/F(g,e-1)-g)/e)=>d>y|d<-y?R(b,e,g+d,y/.99):g,
  F(R(x,f),e*f)
)

FireFoxまたはFireBugコンソールでテストする

for (i=0;i<100;i++)
{
  b=Math.random()*3000
  e=Math.random()*100-50
  p1=Math.pow(b,e) // standard power function, to check
  p2=P(b,e)
  d=(p1-p2)/p1 // relative difference
  if (!isFinite(p2) || d > 0.001) 
    console.log(i, b, e, p1, p2, d.toFixed(3))
}

良い仕事です。それほど正確ではありませんが、アルゴリズムは素晴らしいです=)
flawr 14

あなたはこれが何を説明することができますe&1&&(r*=b)乗算を除いて、ないrb
flawr 14

1
@flawrif(e&1 != 0) r *= b
bebe

おかげで、私はその悪用に気づいていませんでしたが、それはゴルフに適しているようです=)
flawr

1
ここで働くコードは次のとおりです。P=(x,e)=>(F=(b,e,r=1)=>e?F(b*b,e>>1,e&1?r*b:r):r,R=(b,e,g=1,y=1e-16,d=(b/F(g,e-1)-g)/e)=>d>y|d<-y?R(b,e,g+d):g,e<0&&(x=1/x,e=-e),f=1<<24,F(R(x,f),e*f))(私は疲れている必要があります)
BEBE

6

ハスケル、85 90

標準のexp-logアルゴリズム。別の名前を使用して、さらにいくつかの文字を削除します。

a%b|a>1=1/(1/a)%b|0<1=sum$scanl((/).((-b*foldr1(\n b->(1-a)*(b+1/n))c)*))1c
c=[1..99]

raise(%)、または%中置記法で呼び出され、使用するバイト数を減らします:4.5%(-4.5)

ungolfedバージョンも172バイトしか使用しません。

raise a b | a > 1     = 1 / raise (1/a) b
          | otherwise = expo (-b* ln (1-a))

ln x = foldr1 (\n a -> x*a+x/n) [1..99]

expo x = sum $ scanl ((/) . (x*)) 1 [1..99]

4

JS(ES6)、103バイト

t=(x,m,f)=>{for(r=i=s=u=1;i<1<<7+f;r+=s/(u=i++*(f?1:u)))s*=m;return r};e=(a,b)=>t(b,t(a,1-1/a,9)*b-b,0)

例:

e(1.234,5.678) = 3.299798925315965
e(4.5,4.5)     = 869.8739233782269
e(4.5,-4.5)    = 0.0011495918812070608

テイラー級数を使用します。自然対数近似
b^x = 1 + ln(b)*x/1! + (ln(b)*x)^2/2! + (ln(b)*x)^3/3! + (ln(b)*x)^4/4! + ...

ln(b) = (1-1/x) + (1-1/x)^2/2 + (1-1/x)^3/3 + (1-1/x)^4/4 + ...

128回の反復を計算に使用しb^x(階乗のためにそれ以上の反復は困難です)、262144回の反復を使用しましたln(b)


たぶんあなたはゴルフを減らすべきですが、より正確に追加するe(80,5) ->1555962210.2240903必要があります。-3276800000
edc65

@ edc65、あなたは正しい、さらに5文字修正されました。
マイケルM. 14

1
いくつかの異なるアプローチを見るのはとてもいいことです!
flawr

3

golflua 120

という事実を使用します

a^b = exp(log(a^b)) = exp(b*log(a))

独自のlogexp関数を作成しました。ターミナルで実行する場合、値ab改行を入力する必要があります。

\L(x)g=0~@ i=1,50 c=(x-1)/x~@j=2,i c = c*(x-1)/x$g=g+c/i$~g$\E(x)g=1;R=1e7~@i=1,R g=g*(1+x/R)$~g$a=I.r()b=I.r()w(E(b*L(a)))

サンプルの実行:

4.5, 4.5  ==> 869.87104890175
4.5, -4.5 ==> 0.0011495904124065
3.0, 2.33 ==> 12.932794624815
9.0, 0.0  ==> 1
2.0, 2.0  ==> 3.9999996172672

ルアのないバージョンは、

-- returns log
function L(x)
   g = 0
   for i=1,50 do
      c=(x-1)/x
      for j=2,i do
         c = c*(x-1)/x
      end
      g = g + c/i
   end
   return g
end

-- returns exp
function E(x)
   g=1;L=9999999
   for i=1,L do
      g=g*(1+x/L)
   end
   return g
end

a=io.read()
b=io.read()

print(E(b*L(a)))
print(a^b)

いくつかの出力例を提供できますか?
flawr 14

@flawr:私は私ができると仮定...と今行って
カイルKanos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.