Bir sayının süper kökünü hesapla


10

Matematikte tetrasyon, üs alma işleminden sonraki hiper operatördür ve yinelemeli üs alma olarak tanımlanır.

Toplama ( bir başarılı n defa)

Çarpma ( bir tek başına ilave edildi n kez)

Üs ( bir tek başına ile çarpılır, n kere)

Tetrasyon ( kendi başına bir katlanarak, n kez)

Tetrasyonun ters ilişkilerine süper kök ve süper logaritma denir. Göreviniz B dışarı A ve B, baskılar göz önüne alındığında, bir program yazmaktır nd A. mertebeden süper root

Örneğin:

  • A = 65,536ve B = ise 4yazdırır2
  • A = 7,625,597,484,987ve B = ise 3yazdırır3

A ve B pozitif tamsayılardır ve sonuç ondalık noktadan sonra 5 basamak hassasiyetle kayan nokta sayısı olmalıdır. Sonuç gerçek alana aittir.

Dikkatli olun, süper köklerin birçok çözümü olabilir.


1
Giriş numaralarında minimum / maksimum sınırlar var mı? Geçerli bir cevap kayan nokta cevaplarını mı yoksa yalnızca tamsayıyı mı desteklemeli?
Josh

3
Birden fazla çözüm varsa, program tümünü mi yoksa sadece birini mi bulmalı?
Johannes H.

5
Peki kazanma ölçütleriniz nedir?
Mhmd

2
Belirli bir A ve B ≥ 1 için birden fazla çözümü olan bir süper köke basit bir örnek verebilir misiniz?
Tobia

1
Bir süper kökün matematiksel temsilini verebilir misiniz? Korkarım hala nasıl tanımlandığını anlamıyorum.

Yanıtlar:


6

C - netliği amaçlayan, kodu sıkıştırmaya çalışmadı

Girdi dikkate alındığında:

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

O zaman ℝ 'da genellikle tek bir çözüm bulunmalıdır, bu da sorunu önemli ölçüde basitleştirir.

Kod:

#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;
}

Derlemek için:

gcc -o tet_root tet_root.c -lm

Koşmak:

./tet_root A B

Örneğin:

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 ½ ) ➙ 2 n ➙ ∞ olarak? (iyi bilinen sınır)

$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

Evet!

n (e 1 / e ) ➙ ∞, n ➙ ∞ olarak? (üst sınırlar)

$ ./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

Güzel! (e 1 / e ≅ 1.44466786101 ...)


Aslında matematik hakkında çok şey biliyorsunuz :) (Bu cevap) ∈ (gerçekten etkileyici şeyler)
Albert Renshaw

@AlbertRenshaw Bu sadece bir bölünme uygulamasıdır. Hiç de zor değil.
Simply Beautiful Art

5

Python, 87 karakter

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

Cevap için basit bir doğrusal arama.

Konu dışı, ancak python **operatörünün * # $ (@!

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

Hata raporuna değer mi?
Josh

İlişkilendirme engel oluyor mu? Belki karşılaştırdığınız (1e200)**2için 1e(200**2)?
danmcardle

2
@Josh: Bir hata bildirdim: bugs.python.org/issue20543 Temel olarak, amaçlandığı gibi çalışıyor - IEEE float için pek fazla değiller. Eğer bir şeyi düzeltecek olsaydı OverflowError, ilk durumda bir tane oluşturmak olurdu .
Keith Randall

3

Mathematica, 35 40

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

5 basamak hassasiyetle tüm çözümlerin bir listesini oluşturur.

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

Güncellenen kuralların talep ettiği sadece gerçek çözümü elde etmek için 5 karakter daha.


2

Julia

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

Soru yalnızca tamsayıların davranışını tanımladığından kayan nokta komutu yoksayıldı.


2

Bu ne zaman bir kod golf haline geldi? Ben en iyi algoritma ile gelip bir kod meydan okuma olduğunu düşündüm!


APL, 33 karakter

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

Bu, basit bir doğrusal arayıştır = 1 + 10 ° C den başlayan -6 ve bunu 10 ile artan -6 kadar
    günlük günlük log ⋯ bir ≤ 1
günlük burada fonksiyonu yinelemeli B kez uygulanır.

Örnekler

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

Bu kod çok yavaştır, ancak 2 veya 3 gibi küçük bazlar için birkaç saniye içinde tamamlanır. Daha iyi bir şey için aşağıya bakın.


APL, logaritmik karmaşıklık

Aslında kök düzeninde doğrusal karmaşıklık, sonuç boyutu ve hassasiyette logaritmik:

    zaman = O (B × log (C) + B × log (D))

burada B kök düzeni, C istenen tetratasyon tabanıdır ve D istenen hassasiyetin basamak sayısıdır. Bu karmaşıklık benim sezgisel anlayışımdır, resmi bir kanıt üretmedim.

Bu algoritma büyük tamsayılar gerektirmez, sadece normal kayan nokta sayılarında günlük işlevini kullanır, bu nedenle kayan nokta uygulamasının sınırına (çift kesinlikli veya rastgele büyük FP numaraları) kadar çok büyük sayılar üzerinde oldukça etkilidir. Bunları sunan APL uygulamaları.)

Sonucun hassasiyeti ⎕CT(karşılaştırma toleransı) istenen kabul edilebilir hataya ayarlanarak kontrol edilebilir (sistemimde varsayılan olarak 1e¯14, kabaca 14 ondalık basamak)

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≥⍵⍟⍣nYukarıdaki bir Etki Alanı Hatası ile başarısız olup olmadığından emin değilim (çünkü negatif bir argümanın günlüğü hemen başarısız olabilir veya alan adında olmayan karmaşık bir sonuç verebilir ), ancak bulamadım başarısız olan bir dava.

Örnekler

      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' tam bir değer olarak ortaya çıkar çünkü ikili aramanın doğrudan çarptığı değerlerden biri olur (2'den başlayarak, 4'ten ikiye, iki ila 3'e). Bu gerçekleşmeyen genel durumda, sonuç ⎕CT hatası ile kök değerine yaklaşık olarak yaklaşacaktır (daha kesin olarak, her aday tabanın logaritmik testi ⎕CT toleransı ile gerçekleştirilir.)


1

Ruby, 79 bayt

->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}

Bu, aşağıdaki programla aynıdır, ancak yalnızca 99 döngü çalıştırdığından daha az doğrudur.

Ruby, 87 bayt

->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}

Çevrimiçi deneyin

Bu sadece ikidir. Ungolfed:

-> 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 karakter]

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

Kendi yazının değişik bir versiyonu n inci kökü

Misal:

{{{((%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

Haskell

Basit doğrusal arama, önce döner, en küçük eşleşme bulundu.

{-
    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))

Misal

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

0

Mathematica, optimizasyon olmadan 41 bayt

Mathematica temel olarak böyle problemleri çözmek için icat edildi. Kolay bir çözüm, sorunu iç içe bir güç serisi olarak oluşturmak ve Reducedenklemlere analitik çözümler arayan yerleşik işleve aktarmaktır. Sonuç olarak, aşağıdakiler, alışılmadık şekilde özlü kod olmanın yanı sıra, kaba kuvvet de değildir.

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

Sabırlıysanız ve altı bayt kaydetmek istiyorsanız, yalnızca Gerçek sayı çözümleri sağlama kısıtlamasını kaldırabilirsiniz. Birkaç bayt kaydetmek için iç içe geçmiş işlevlerin bazılarını kısaltılmış olarak da ifade edebilirsiniz. Verildiği gibi, bu şekilde geri döner

resim açıklamasını buraya girin


0

05AB1E , 16 bayt

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

Port @KeithRandall 'in Python cevap .

Çevrimiçi deneyin.

Açıklama:

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²>и.»maynı bayt sayısı için de olabilir :

  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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.