คำนวณค่ารูทรากของตัวเลข


10

ในคณิตศาสตร์ tetration เป็นตัวดำเนินการไฮเปอร์ถัดไปหลังจากการยกกำลังและถูกกำหนดเป็นการยกกำลังซ้ำ

นอกจาก ( ประสบความสำเร็จnครั้ง)

คูณ ( เพิ่มให้กับตัวเองnครั้ง)

ยกกำลัง ( คูณด้วยตัวเองnครั้ง)

Tetration ( exponentiated ด้วยตัวเองnครั้ง)

ความสัมพันธ์แบบผกผันของการทดลองเรียกว่า super-root และ super-logarithm งานของคุณคือการเขียนโปรแกรมที่ให้ A และ B, พิมพ์ออกขครั้ง -order ซุปเปอร์รากของ A.

ตัวอย่างเช่น:

  • ถ้า A = 65,536และ B = 4มันพิมพ์2
  • ถ้า A = 7,625,597,484,987และ B = 3มันพิมพ์3

A และ B เป็นจำนวนเต็มบวกและผลลัพธ์ต้องเป็นเลขทศนิยมที่มีความแม่นยำ 5 หลักหลังจุดทศนิยม ผลลัพธ์เป็นของโดเมนจริง

ระวังรากสุดอาจมีวิธีแก้ปัญหามากมาย


1
มีการ จำกัด จำนวนขั้นต่ำ / สูงสุดในการป้อนข้อมูลหรือไม่? คำตอบที่ถูกต้องควรรองรับการตอบแบบทศนิยมหรือเป็นจำนวนเต็มเท่านั้น?
Josh

3
หากมีหลายวิธีโปรแกรมควรค้นหาทั้งหมดหรือเพียงหนึ่ง?
Johannes H.

5
เกณฑ์การชนะของคุณคืออะไร
Mhmd

2
คุณสามารถยกตัวอย่างง่ายๆของ super-root ที่มีมากกว่าหนึ่งวิธีสำหรับ A และ B ≥ 1 ที่กำหนดได้หรือไม่?
เบีย

1
คุณสามารถให้ตัวแทนทางคณิตศาสตร์ของซุปเปอร์รูทได้หรือไม่? ฉันเกรงว่าฉันยังไม่เข้าใจว่ามันถูกกำหนดไว้อย่างไร

คำตอบ:


6

C - เล็งเพื่อความชัดเจนไม่ได้พยายามบีบรหัส

กำลังพิจารณาอินพุต:

A: A ∈ ℝ, A ≥ 1.0
B: B ∈ ℕ, B ≥ 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 ½ ) ➙ 2 เป็น n ➙∞? (ขีด จำกัด ที่รู้จักกันดี)

$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

ใช่

n (e 1 / e ) ➙∞เป็น 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 ... )


จริง ๆ แล้วคุณรู้มากเกี่ยวกับคณิตศาสตร์ฉันสามารถบอกได้ :) (คำตอบนี้) ∈ (สิ่งที่น่าประทับใจℝeally)
อัลเบิร์ต Renshaw

@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

การค้นหาเชิงเส้นอย่างง่ายสำหรับคำตอบ

นอกหัวข้อ แต่สิ่งที่ # # (@! ขึ้นกับตัว**ดำเนินการหลาม?

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

2
@ Josh: ฉันรายงานข้อผิดพลาด: bugs.python.org/issue20543 โดยพื้นฐานแล้วทำงานได้ตามที่ตั้งใจ - พวกมันไม่ค่อยมีอะไรมากสำหรับ IEEE float หากพวกเขาจะแก้ไขอะไรก็จะต้องสร้างOverflowErrorในกรณีแรก
Keith Randall

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และเพิ่มขึ้นทีละ 10 -6จนกระทั่ง
    ล็อกล็อกCล็อกCล็อกC ⋯ A ≤ 1
ที่ฟังก์ชันบันทึกCถูกนำไปใช้ซ้ำ B ครั้ง

ตัวอย่าง

      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 คือจำนวนตัวเลขของความแม่นยำที่ถาม ความซับซ้อนนี้เป็นความเข้าใจที่เข้าใจง่ายของฉันฉันไม่ได้พิสูจน์อย่างเป็นทางการ

อัลกอริทึมนี้ไม่จำเป็นต้องมีจำนวนเต็มขนาดใหญ่เพียงใช้ฟังก์ชั่นการบันทึกบนเลขทศนิยมปกติเท่านั้นดังนั้นมันจึงค่อนข้างมีประสิทธิภาพสำหรับจำนวนมากถึงขีด จำกัด ของการใช้จุดลอยตัว (ไม่ว่าจะเป็นความแม่นยำสองเท่า การใช้งาน APL ที่ให้บริการ)

ความแม่นยำของผลลัพธ์สามารถควบคุมได้โดยการตั้งค่า⎕CT( ค่าเผื่อการเปรียบเทียบ) กับข้อผิดพลาดที่ยอมรับได้ (ในระบบของฉันค่าเริ่มต้นคือ1e¯14, ประมาณ 14 หลักทศนิยม)

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' ออกมาเป็นค่าที่แน่นอนเพราะมันเป็นหนึ่งในค่าที่ได้รับโดยตรงจากการค้นหาแบบไบนารี ในกรณีทั่วไปที่ไม่ได้เกิดขึ้นดังนั้นผลลัพธ์จะใกล้เคียงกับค่ารูทที่มีข้อผิดพลาด⎕CT (แม่นยำยิ่งขึ้นการทดสอบลอการิทึมของฐานผู้สมัครทุกคนจะดำเนินการด้วยความอดทน⎕CT)


1

ทับทิม 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 ลูป

ทับทิม 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}

ลองออนไลน์

นี่เป็นแค่การแบ่งครึ่ง 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 ตัวอักษร]

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

แก้ไขฉบับของโพสต์ของตัวเองn THราก

ตัวอย่าง:

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

ค้นหาเชิงเส้นอย่างง่ายส่งคืนแรกพบคู่ที่เล็กที่สุด

{-
    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 ถูกคิดค้นโดยทั่วไปในการแก้ปัญหาเช่นนี้ ทางออกหนึ่งที่ง่ายคือการสร้างปัญหาเป็นชุดพลังงานที่ซ้อนกันและส่งผ่านไปยังReduceฟังก์ชั่นในตัวซึ่งหาวิธีการแก้ปัญหาการวิเคราะห์สมการ เป็นผลให้ต่อไปนี้นอกเหนือจากการเป็นรหัสรัดกุมผิดปกติก็ไม่ได้กำลังดุร้าย

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

คุณสามารถลบข้อ จำกัด เพื่อให้บริการโซลูชั่นจำนวนจริงเท่านั้นหากคุณอดทนและต้องการบันทึกหกไบต์ นอกจากนี้คุณยังสามารถแสดงฟังก์ชั่นที่ซ้อนกันบางอย่างในรูปแบบย่อเพื่อบันทึกอีกสองสามไบต์ ตามที่ระบุไว้จึงส่งคืนดังนั้น

ป้อนคำอธิบายรูปภาพที่นี่


0

05AB1E , 16 ไบต์

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

ท่าเรือ@KeithRandall 's คำตอบหลาม

ลองออนไลน์

คำอธิบาย:

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.