Tính siêu gốc của một số


10

Trong toán học, tetration là toán tử siêu tiếp theo sau lũy thừa và được định nghĩa là lũy thừa lặp.

Ngoài ra ( một lần n thành công )

Nhân ( một bổ sung vào bản thân, n lần)

Lũy thừa ( một nhân với chính nó, n lần)

Tetration ( một cấp số nhân của chính nó, n lần)

Các mối quan hệ nghịch đảo của tetration được gọi là siêu gốc và siêu logarit. Nhiệm vụ của bạn là viết một chương trình, cho A và B, in ra siêu gốc thứ B của A.

Ví dụ:

  • nếu A = 65,536và B = 4nó in2
  • nếu A = 7,625,597,484,987và B = 3nó in3

A và B là các số nguyên dương và kết quả phải là số dấu phẩy động với độ chính xác là 5 chữ số sau dấu thập phân. Kết quả thuộc về miền thực.

Hãy cẩn thận, siêu rễ có thể có nhiều giải pháp.


1
Có giới hạn tối thiểu / tối đa trên các số đầu vào không? Nên một câu trả lời hợp lệ hỗ trợ câu trả lời dấu phẩy động, hoặc chỉ số nguyên?
Josh

3
Nếu nhiều giải pháp, chương trình nên tìm tất cả hay chỉ một?
Julian H.

5
Vậy tiêu chí chiến thắng của bạn là gì?
Mhmd

2
Bạn có thể đưa ra một ví dụ đơn giản về một siêu gốc có nhiều hơn một giải pháp cho A và B ≥ 1 đã cho không?
Tobia

1
Bạn có thể đưa ra biểu diễn toán học của một siêu gốc? Tôi sợ tôi vẫn không hiểu nó được định nghĩa như thế nào.

Câu trả lời:


6

C - nhằm mục đích rõ ràng, đã không cố gắng để ép mã

Xem xét đầu vào:

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

Sau đó, thường chỉ có một giải pháp trong, giúp đơn giản hóa vấn đề đáng kể.

Mã là:

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

Để biên dịch:

gcc -o tet_root tet_root.c -lm

Chạy:

./tet_root A B

Ví dụ:

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 là n ➙? (giới hạn nổi tiếng)

$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

Đúng!

n (e 1 / e ) như n ➙? (Giới hạn trê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

Mát mẻ! (e 1 / e ≅ 1.44466786101 ...)


Bạn thực sự biết rất nhiều về toán học tôi có thể nói :) (Câu trả lời này) (thứ thực sự ấn tượng)
Albert Renshaw

@AlbertRenshaw Đây chỉ là một triển khai chia đôi. Không khó lắm đâu.
Nghệ thuật đơn giản đẹp

5

Python, 87 ký tự

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

Một tìm kiếm tuyến tính đơn giản cho câu trả lời.

Không có chủ đề, nhưng * # $ (@! Là gì với **toán tử python ?

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

Đáng giá một báo cáo lỗi?
Josh

Là sự kết hợp có được cản trở? Có lẽ bạn đang so sánh (1e200)**2với 1e(200**2)?
danmcardle

2
@Josh: Tôi đã báo cáo một lỗi: bug.python.org/su20543 Về cơ bản, hoạt động như dự định - chúng không có nhiều cho IEEE float. Nếu họ phải sửa bất cứ thứ gì, thì đó là tạo ra một OverflowErrortrường hợp đầu tiên.
Keith Randall

3

Toán học, 35 40

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

Tạo một danh sách tất cả các giải pháp, với độ chính xác 5 chữ số.

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

Thêm 5 ký tự để chỉ nhận được giải pháp thực sự, mà các quy tắc cập nhật yêu cầu.


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

Bỏ qua hướng dẫn dấu phẩy động vì câu hỏi chỉ xác định hành vi cho số nguyên.


2

Khi nào thì điều này trở thành một mã golf? Tôi nghĩ rằng đó là một thách thức mã để đưa ra thuật toán tốt nhất!


APL, 33 ký tự

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

Đây là một tìm kiếm tuyến tính đơn giản, bắt đầu từ C = 1 + 10 -6 và tăng nó lên 10 -6 cho đến khi
    log C log C log C ⋯ A 1
trong đó hàm log C được áp dụng đệ quy B lần.

Ví dụ

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

Mã này rất chậm, nhưng đối với các cơ sở nhỏ như 2 hoặc 3, nó sẽ hoàn thành trong vài giây. Xem dưới đây cho một điều tốt hơn.


APL, độ phức tạp logarit

Thực tế độ phức tạp tuyến tính trên thứ tự gốc, logarit về kích thước và độ chính xác của kết quả:

    thời gian = O (nhật ký B × (C) + B × nhật ký (D))

Trong đó B là thứ tự gốc, C là cơ sở tetration được yêu cầu và D là số chữ số chính xác được yêu cầu. Sự phức tạp này là sự hiểu biết trực quan của tôi, tôi đã không đưa ra một bằng chứng chính thức.

Thuật toán này không yêu cầu số nguyên lớn, nó chỉ sử dụng hàm log trên các số dấu phẩy động thông thường, do đó nó khá hiệu quả với các số rất lớn, cho đến giới hạn của việc thực hiện dấu phẩy động (chính xác gấp đôi hoặc số FP lớn tùy ý trên Triển khai APL cung cấp cho họ.)

Độ chính xác của kết quả có thể được kiểm soát bằng cách đặt ⎕CT(dung sai so sánh) thành lỗi chấp nhận được mong muốn (trên hệ thống của tôi, nó mặc định là 1e¯14, khoảng 14 chữ số thập phân)

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

Tôi không chắc liệu 1≥⍵⍟⍣nở trên có thể thất bại với Lỗi miền hay không (vì nhật ký của đối số phủ định có thể thất bại ngay lập tức hoặc đưa ra một kết quả phức tạp, không thuộc miền ) nhưng tôi không thể tìm thấy một trường hợp thất bại

Ví dụ

      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' xuất hiện dưới dạng một giá trị chính xác bởi vì nó là một trong những giá trị được tìm kiếm trực tiếp bởi tìm kiếm nhị phân (bắt đầu từ 2, nhân đôi thành 4, chia thành 3). Trong trường hợp chung không xảy ra, do đó, kết quả sẽ xấp xỉ giá trị gốc với lỗi ⎕CT (chính xác hơn là kiểm tra logarit của mọi cơ sở ứng cử viên được thực hiện với dung sai ⎕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}

Điều này giống như chương trình dưới đây, nhưng kém chính xác hơn vì nó chỉ chạy 99 vòng.

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}

Dùng thử trực tuyến

Điều này chỉ đơn giản là chia đôi. Ung dung:

-> 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 ký tự]

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

Một phiên bản sửa đổi của bài riêng tôi n th gốc

Thí dụ:

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

Tìm kiếm tuyến tính đơn giản, trả về đầu tiên, tìm thấy kết quả khớp nhỏ nhất.

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

Thí dụ

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

0

Mathicala, 41 byte mà không cần tối ưu hóa

Mathematica về cơ bản đã được phát minh để giải quyết các vấn đề như thế này. Một giải pháp dễ dàng là xây dựng bài toán dưới dạng chuỗi lũy thừa lồng nhau và chuyển nó sang Reducehàm tích hợp, tìm kiếm các giải pháp phân tích cho các phương trình. Kết quả là, sau đây, ngoài mã ngắn gọn khác thường, cũng không phải là vũ lực.

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

Bạn có thể xóa giới hạn chỉ cung cấp giải pháp số thực nếu bạn kiên nhẫn và muốn lưu sáu byte. Bạn cũng có thể biểu thị một số hàm lồng nhau ở dạng viết tắt để lưu thêm một vài byte. Như đã cho, nó trở lại như vậy

nhập mô tả hình ảnh ở đây


0

05AB1E , 16 byte

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

Cổng câu trả lời Python của @KeithRandall .

Hãy thử trực tuyến.

Giải trình:

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}cũng có thể D²>и.»mcho cùng một số byte:

  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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.