数値のスーパールートを計算する


10

数学では、テトラションは累乗の後の次のハイパー演算子であり、反復累乗として定義されます。

また、(成功のn倍)

乗算(それ自体に加え、N回)

べき乗(自体を乗じ、N回)

テトレーション(単独で累乗、N回)

テトラションの逆関係は、スーパールート、スーパーログと呼ばれます。あなたの仕事は、AとBを考えると、Bを出力し、そのプログラムを書くことであるND A.の-orderスーパールート

例えば:

  • A = 65,536およびB =の4場合2
  • A = 7,625,597,484,987およびB =の3場合3

AとBは正の整数であり、結果は小数点以下5桁の精度の浮動小数点数でなければなりません。結果は実際のドメインに属します。

スーパールートには多くの解決策があるかもしれないので注意してください。


1
入力数値に最小/最大の境界はありますか?有効な回答は浮動小数点回答をサポートする必要がありますか、それとも整数のみですか?
Josh、

3
複数の解決策がある場合、プログラムはすべてを見つけるべきですか、それとも1つだけを見つけるべきですか?
Johannes H. 14

5
それであなたの勝利基準は何ですか?
Mhmd 2014

2
特定のAおよびB≥1に対して複数の解を持つスーパールートの簡単な例を挙げられますか?
トビア2014

1
スーパールートの数学的表現を与えることができますか?それがどのように定義されているのかまだ理解できていません。

回答:


6

C —明確にするために、コードを絞り込もうとしませんでした

入力を考慮:

A: A ∈ ℝ, A ≥ 1.0
B: B ∈ ℕ, B ≥ 1

その場合、通常、inには1つのソリューションしかなく、問題が大幅に簡略化されます。

コードは:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define TOLERANCE    1.0e-09

double tetrate(double, int);

int main(int argc, char **argv)
{
    double target, max, min, mid, working;
    int levels;

    if (argc == 3)
    {
        target = atof(argv[1]); // A
        levels = atoi(argv[2]); // B

        // Shortcut if B == 1
        if (levels == 1)
        {
            printf("%f\n", target);
            return 0;
        }

        // Get a first approximation
        max = 2.0;
        while (tetrate(max, levels) < target)
            max *= 2.0;

        min = max / 2.0;

        // printf("Answer is between %g and %g\n", min, max);

        // Use bisection to get a closer approximation
        do
        {
            mid = (min + max) / 2.0;
            working = tetrate(mid, levels);
            if (working > target)
                max = mid;
            else if (working < target)
                min = mid;
            else
                break;
        }
        while (max - min > TOLERANCE);

        // printf("%g: %f = %f tetrate %d\n", target, tetrate(mid, levels), mid, levels);
        printf("%f\n", mid);
    }

    return 0;
}

double tetrate(double d, int i)
{
    double result = d;

    // If the result is already infinite, don't tetrate any more
    while (--i && isfinite(result))
        result = pow(d, result);

    return result;
}

コンパイルする:

gcc -o tet_root tet_root.c -lm

走る:

./tet_root A B

例えば:

4 2

$ ./tet_root 65536 4
2.000000

3 3

$ ./tet_root 7625597484987 3
3.000000

3個の π

$ ./tet_root 1.340164183e18 3
3.141593

n)➙2 as n➙∞?(既知の制限)

$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

はい!

n(e 1 / e)➙∞as n➙∞?(上限)

$ ./tet_root 9.999999999e199 100
1.445700

$ ./tet_root 9.999999999e199 1000
1.444678

$ ./tet_root 9.999999999e199 10000
1.444668

$ ./tet_root 9.999999999e199 100000
1.444668

涼しい!(e 1 / e≅1.44466786101 ...)


あなたは実際に私が言うことができる数学について多くを知っています:)(この答え)ℝ(本当に印象的なもの)
アルバート・レンショー14

@AlbertRenshawこれは二分法の単なる実装です。それほど難しいことではありません。
単に美しい芸術

5

Python、87文字

E=lambda x,n:x**E(x,n-1)if n else 1
def S(A,B):
 x=1.
 while E(x,B)<A:x+=1e-5
 return x

答えの単純な線形検索。

トピック外ですが、*#$(@!はpython **演算子で何ができていますか?

>>> 1e200*1e200
inf
>>> 1e200**2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Numerical result out of range')

バグレポートに値する?
Josh

関連性が邪魔になっていますか?おそらくあなたは比較(1e200)**2してい1e(200**2)ますか?
danmcardle 2014

2
@ジョシュ:私はバグを報告しました:bugs.python.org/issue20543 基本的に、意図したとおりに機能します-IEEEフロートにはあまり対応していません。彼らが何かを修正するOverflowError場合は、最初のケースでを生成することになります。
キースランダル14

3

Mathematica、35 40

n /. Solve[Nest[#^(1/n) &, a, b] == n]~N~5

5桁の精度で、すべてのソリューションのリストを生成します。

n /. Last@Solve[Nest[#^(1/n) &, a, b] == n]~N~5

更新されたルールが要求する実際のソリューションのみを取得するために、さらに5文字。


2

ジュリア

julia> t(a,b)=(c=a;for j=1:b-1;c=a^c;end;c)
julia> s(c,b)=(i=1;while t(i,b)!=c;i+=1;end;i)
julia> s(65536,4)
2
julia> s(7625597484987,3)     
3

質問は整数の動作のみを定義しているため、浮動小数点命令は無視されました。


2

これはいつコードゴルフになったのですか?最高のアルゴリズムを思いつくのはコードの挑戦だと思いました!


APL、33文字

{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}

これは単純な線形検索で、C = 1 + 10 -6から始まり 、log C関数が再帰的にB回適用される     log C log C log C ⋯A≤1になるまで10 -6ずつインクリメントします。

      4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
      3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113

このコードは非常に低速ですが、2や3などの小さなベースの場合、数秒で完了します。より良いことについては以下を参照してください。


APL、対数の複雑さ

実際にはルート次数で線形の複雑さ、結果のサイズと精度で対数:

    時間= O(B×log(C)+ B×log(D))

ここで、Bはルート次数、Cは求められるテトラションベース、Dは求められる精度の桁数です。この複雑さは私の直感的な理解であり、正式な証明を作成していません。

このアルゴリズムは大きな整数を必要とせず、通常の浮動小数点数で対数関数のみを使用するため、浮動小数点実装の制限(倍精度、または任意の大きなFP数)それらを提供するAPL実装。)

結果の精度は、⎕CT(比較許容誤差)を望ましい許容誤差に設定することで制御できます(私のシステムでは、デフォルトで1e¯14、およそ14桁の10進数)。

sroot←{              ⍝ Compute the ⍺-th order super-root of ⍵:
  n←⍺ ⋄ r←⍵          ⍝ n is the order, r is the result of the tetration.
  u←{                ⍝ Compute u, the upper bound, a base ≥ the expected result:
    1≥⍵⍟⍣n⊢r:⍵       ⍝   apply ⍵⍟ (log base ⍵) n times; if ≤1 then upper bound found
    ∇2×⍵             ⍝   otherwise double the base and recurse
  }2                 ⍝ start the search with ⍵=2 as a first guess.
  (u÷2){             ⍝ Perform a binary search (bisection) to refine the base:
    b←(⍺+⍵)÷2        ⍝   b is the middle point between ⍺ and ⍵
    t←b⍟⍣n⊢r         ⍝   t is the result of applying b⍟ n times, starting with r;
    t=1:b            ⍝   if t=1 (under ⎕CT), then b is the super-root wanted;
    t<1:⍺∇b          ⍝   if t<1, recurse between ⍺ and b
    b∇⍵              ⍝   otherwise (t>1) returse between b and ⍵
  }u                 ⍝ begin the search between u as found earlier and its half.
}

1≥⍵⍟⍣n上記がドメインエラーで失敗するかどうかはわかりません(負の引数のログはすぐに失敗するか、複雑な結果を返す可能性があるため、のドメインには含まれません)。失敗したケース。

      4 sroot 65536
1.9999999999999964
      4 sroot 65537
2.000000185530773
      3 sroot 7625597484987
3
      3 sroot 7625597400000
2.999999999843567
      3 sroot 7625597500000
3.000000000027626

「3」は、バイナリ検索で直接ヒットした値の1つであるため、正確な値として出力されます(2から始まり、2倍から4倍、3倍から3倍)。発生しない一般的なケースでは、結果はルート値を⎕CTエラーで近似します(より正確には、すべての候補ベースの対数検定は⎕CT許容誤差で実行されます)。


1

Ruby、79バイト

->a,b{x=y=1.0;z=a;eval"y=(x+z)/2;x,z=a<eval('y**'*~-b+?y)?[x,y]:[y,z];"*99;p y}

これは以下のプログラムと同じですが、99ループしか実行しないため、正確性は低下します。

Ruby、87バイト

->a,b{x=y=1.0;z=a;(y=(x+z)/2;x,z=a<eval("y**"*~-b+?y)?[x,y]:[y,z])while y!=(x+z)/2;p y}

オンラインでお試しください

これは単に二等分です。非ゴルフ:

-> a, b {
    # y^^b by evaluating the string "y ** y ** ..."
    tetration =-> y {eval "y ** " * (b-1) + ?y}

    lower = middle = 1.0
    upper = a

    while middle != (lower + upper) / 2 do
        middle = (lower + upper) / 2

        if tetration[middle] > a
            upper = middle
        else
            lower = middle
        end
    end

    print middle
}

0

k [52文字]

{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}

私自身の投稿n 番目のルートの修正版

例:

{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}[7625597484987;3]
3f 

{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}[65536;4]
2f

0

ハスケル

単純な線形検索。最初に見つかった最小の一致を返します。

{-
    The value of a is the result of exponentiating b some number of times.
    This function computes that number.
-}
superRoot a b = head [x | x<-[2..a], tetrate x b == a]

{-
    compute b^b^...^b repeated n times
-}
tetrate b 1 = b
tetrate b n = b^(tetrate b (n-1))

*Main> superRoot 65536 4
2
*Main> superRoot 7625597484987 3
3

0

Mathematica、41バイト、最適化なし

Mathematicaは基本的にこのような問題を解決するために発明されました。簡単な解決策の1つは、ネストされたべき級数として問題を構築し、それを組み込みReduce関数に渡すことです。組み込み関数は、方程式の分析解を求めます。その結果、以下は、非常に簡潔なコードであることに加えて、総当たりではありません。

Reduce[Nest[Power[#, 1/x] &, a, b] == x, x, Reals]

辛抱強く6バイトを節約したい場合は、制限を解除して実数ソリューションのみを提供できます。ネストされた関数のいくつかを省略形で表現して、さらに数バイトを節約することもできます。与えられたように、それはこのように戻ります

ここに画像の説明を入力してください


0

05AB1E、16 バイト

1[ÐU²FXm}¹@#5(°+

@KeithRandallのPython回答のポート。

オンラインでお試しください。

説明:

1                 # Push a 1
 [                # Start an infinite loop:
  Ð               #  Triplicate the top value on the stack
   U              #  Pop and store one in variable `X`
    ²F            #  Inner loop the second input amount of times:
      Xm          #   And take the top value to the power `X`
        }         #  After the inner loop:
         ¹@       #  If the resulting value is larger than or equal to the first input:
           #      #   Stop the infinite loop
                  #   (after which the top of the stack is output implicitly as result)
            5(°+  #  If not: increase the top value by 10^-5

ÐU²FXm}D²>и.»m同じバイト数の場合もあります:

  D               #   Duplicate the top value on the stack
   ²>             #   Push the second input + 1
     и            #   Repeat the top value that many times as list
                #   Reduce it by:
        m         #    Taking the power
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.