Hitung akar super dari angka


10

Dalam matematika, tetrasi adalah operator hiper berikutnya setelah eksponensial, dan didefinisikan sebagai eksponensial berulang.

Penambahan ( a berhasil n kali)

Perkalian ( a ditambahkan ke dirinya sendiri, n kali)

Eksponensial ( a dikalikan dengan sendirinya, n kali)

Tetrasi ( sebuah eksponen dengan sendirinya, n kali)

Hubungan terbalik tetrasi disebut super-root, dan super-logaritma. Tugas Anda adalah untuk menulis sebuah program yang, diberikan A dan B, print B nd orde kedua super-akar A.

Sebagai contoh:

  • jika A = 65,536dan B = 4itu dicetak2
  • jika A = 7,625,597,484,987dan B = 3itu dicetak3

A dan B adalah bilangan bulat positif dan hasilnya harus angka floating point dengan ketepatan 5 digit setelah titik desimal. Hasilnya milik domain nyata.

Hati-hati, super-root mungkin punya banyak solusi.


1
Apakah ada batas minimum / maksimum pada nomor input? Haruskah jawaban yang valid mendukung jawaban floating point, atau hanya bilangan bulat?
Josh

3
Jika banyak solusi, haruskah program menemukan semua atau hanya satu?
Johannes H.

5
Jadi, apa kriteria kemenangan Anda?
Mhmd

2
Bisakah Anda memberikan contoh sederhana dari super-root yang memiliki lebih dari satu solusi untuk A dan B yang diberikan ≥ 1?
Tobia

1
Bisakah Anda memberikan representasi matematis dari super-root? Saya khawatir saya masih tidak mengerti bagaimana ini didefinisikan.

Jawaban:


6

C - bertujuan untuk kejelasan, tidak berusaha memeras kode

Mempertimbangkan masukan:

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

Maka biasanya hanya ada satu solusi di ℝ, yang menyederhanakan masalah dengan cukup.

Kode adalah:

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

Untuk mengkompilasi:

gcc -o tet_root tet_root.c -lm

Untuk berlari:

./tet_root A B

Misalnya:

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 sebagai n ➙ ∞? (batas terkenal)

$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

Iya!

n (e 1 / e ) ➙ ∞ sebagai n ➙ ∞? (batas atas)

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

Keren! (e 1 / e ≅ 1.44466786101 ...)


Anda sebenarnya tahu banyak tentang matematika yang bisa saya katakan :) (Jawaban ini) ∈ (hal-hal yang sangat mengesankan)
Albert Renshaw

@AlbertRenshaw Ini hanya implementasi pembelahan dua. Sama sekali tidak sulit.
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

Pencarian linear sederhana untuk jawabannya.

Di luar topik, tetapi apa yang * # $ (@! Ada pada **operator python ?

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

Layak untuk laporan bug?
Josh

Apakah asosiatif menghalangi? Mungkin Anda membandingkan (1e200)**2ke 1e(200**2)?
danmcardle

2
@Josh: Saya melaporkan bug: bugs.python.org/issue20543 Pada dasarnya, berfungsi sebagaimana mestinya - mereka tidak banyak untuk IEEE float. Jika mereka memperbaiki apa pun, itu akan menghasilkan OverflowErrordalam kasus pertama.
Keith Randall

3

Mathematica, 35 40

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

Menghasilkan daftar semua solusi, dengan ketepatan 5 digit.

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

5 karakter lagi hanya untuk mendapatkan solusi nyata, yang diminta oleh aturan yang diperbarui.


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

Instruksi floating point diabaikan karena pertanyaan hanya mendefinisikan perilaku untuk bilangan bulat.


2

Kapan ini menjadi kode golf? Saya pikir itu adalah tantangan kode untuk menghasilkan algoritma terbaik!


APL, 33 karakter

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

Ini adalah pencarian linear sederhana, mulai dari C = 1 + 10 -6 dan menambahnya dengan 10 -6 hingga
    log C log C log C ⋯ A ≤ 1 di
mana fungsi log C diterapkan secara berulang B kali.

Contohnya

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

Kode ini sangat lambat, tetapi untuk basis kecil seperti 2 atau 3 selesai dalam beberapa detik. Lihat di bawah untuk hal yang lebih baik.


APL, kompleksitas logaritmik

Sebenarnya kompleksitas linear pada urutan root, logaritmik pada ukuran dan presisi hasil:

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

di mana B adalah urutan root, C adalah basis tetrasi yang diminta, dan D adalah jumlah digit presisi yang diminta. Kompleksitas ini adalah pemahaman intuitif saya, saya belum menghasilkan bukti formal.

Algoritma ini tidak memerlukan bilangan bulat besar, hanya menggunakan fungsi log pada angka floating point reguler, oleh karena itu cukup efisien pada angka yang sangat besar, hingga batas implementasi floating point (baik presisi ganda, atau angka FP besar sembarang pada Implementasi APL yang menawarkannya.)

Ketepatan hasil dapat dikontrol dengan menetapkan ⎕CT(toleransi perbandingan) untuk kesalahan yang dapat diterima yang diinginkan (pada sistem saya itu default ke 1e14, kira-kira 14 digit desimal)

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

Saya tidak yakin apakah di 1≥⍵⍟⍣natas dapat gagal dengan Kesalahan Domain (karena log argumen negatif dapat langsung gagal, atau memberikan hasil yang kompleks, yang tidak akan ada dalam domain ) tetapi saya belum dapat menemukan sebuah kasus yang gagal.

Contohnya

      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' keluar sebagai nilai yang tepat karena kebetulan merupakan salah satu nilai yang langsung terkena oleh pencarian biner (mulai dari 2, dua kali lipat menjadi 4, dua bagian ke 3). Dalam kasus umum yang tidak terjadi, sehingga hasilnya akan mendekati nilai akar dengan kesalahan ⎕CT (lebih tepatnya, uji logaritmik setiap basis kandidat dilakukan dengan toleransi ⎕CT.)


1

Ruby, 79 byte

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

Ini sama dengan program di bawah ini, tetapi kurang akurat karena hanya menjalankan 99 loop.

Ruby, 87 byte

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

Cobalah online

Ini hanya pembelahan dua. Tidak Disatukan:

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

Sebuah versi modifikasi dari posting saya sendiri n th akar

Contoh:

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

Pencarian linear sederhana, mengembalikan yang pertama, kecocokan terkecil ditemukan.

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

Contoh

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

0

Mathematica, 41 byte tanpa optimasi

Mathematica pada dasarnya diciptakan untuk memecahkan masalah seperti ini. Salah satu solusi mudah adalah dengan membangun masalah sebagai rangkaian daya bersarang dan meneruskannya ke Reducefungsi bawaan, yang mencari solusi analitik untuk persamaan. Akibatnya, berikut ini, selain menjadi kode ringkas yang tidak biasa, juga tidak kasar.

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

Anda dapat menghapus batasan untuk hanya menyediakan solusi bilangan real jika Anda sabar dan ingin menghemat enam byte. Anda juga dapat mengekspresikan beberapa fungsi bersarang dalam bentuk yang disingkat untuk menyimpan beberapa byte lagi. Seperti yang diberikan, ia kembali demikian

masukkan deskripsi gambar di sini


0

05AB1E , 16 byte

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

Port jawaban Python @KeithRandall .

Cobalah online.

Penjelasan:

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}bisa juga D²>и.»muntuk byte-count yang sama:

  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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.