Оценка обозначения стрелки Кнута в функции

У меня проблемы с вычислением обозначения стрелки Кнута, которое is и которое можно найти здесь, в функции. Что я сделал до сих пор:

int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value;       // the input I
BigInteger b = (int)bNum.Value;       // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
    result = Power(temp, b);
    temp = r;
    b = a;
}

с силой

BigInteger Power(BigInteger Base, BigInteger Pow)
    {
        BigInteger x = Base;
        for(int i = 0; i < (Pow-1); i++)
        {
            x *= Base;
        }
        return x;
    }

но это неправильно с его значениями, и я не могу найти способ исправить это. Он может обрабатывать задачи с 1 стрелкой, такие как 3 × 3 (что составляет 3 ^ 3 = 9), но он не может обрабатывать больше стрелок, чем эта.

Мне нужен способ, чтобы выяснить больше стрелок, таких как 3 ↑↑ 3,

который должен быть 7625597484987 (3^27), и я получаю 19683 (27 ^ 3). Если бы вы могли помочь мне понять, как я могу получить правильный вывод и объяснить, что я делаю неправильно, я был бы очень признателен.

2 ответа

Решение

Я написал это в Java, и использовать двойной для входного параметра:

    private static double knuthArrowMath(double a, double b, int arrowNum)
{
    if( arrowNum == 1)
        return Math.pow(a, b);
    double result = a;
    for (int i = 0; i < b - 1; i++)
    {
        result = knuthArrowMath(a, result, arrowNum - 1);
    }
    return result;
}

Если вы ожидаете 7625597484987 (3 ^27), но получите 19683 (27^ 3), разве это не простой вопрос - поменять аргументы при вызове функции power?

Смотря на вашу функцию Power, ваш фрагмент кода, кажется, вызывает Power с temp в качестве основы и b в качестве power:

int arrowCount = (int)arrowNum.Value; // Part of
BigInteger a = (int)aNum.Value;       // the input I
BigInteger b = (int)bNum.Value;       // already have
BigInteger result = a;
BigInteger temp = a;
for(int i = 0; i < arrowCount; i++)
{
    result = Power(temp, b);
    temp = result;
    b = a;
}

Не следует временно поменять местами b, чтобы вы получили result = Power(b, temp) получить желаемый результат?

Так проходят 1 результаты звонков Power(3, 3) в результате чего temp = 27 и пройти 2 звонка Power(3, 27), Причина, по которой это работает только для одной стрелки, состоит в том, что переменные для первого Power(base, power) звонок не имеет значения.

Как вы указали в своем ответе, это не охватывает все ситуации. Учитывая приведенные вами примеры, я создал это небольшое консольное приложение:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Arrow(3, 3));
            Console.WriteLine(Arrow(4, 4, 1));
            Console.WriteLine(Arrow(3, 4, 1));
            Console.ReadKey();
        }

        private static BigInteger Arrow(BigInteger baseNumber, BigInteger arrows)
        {
            return Arrow(baseNumber, baseNumber, arrows-1);
        }

        private static int Arrow(BigInteger baseNumber, BigInteger currentPower, BigInteger arrows)
        {
            Console.WriteLine("{0}^{1}", baseNumber, currentPower);
            var result = Power(baseNumber, currentPower);

            if (arrows == 1)
            {
                return result;
            }
            else
            {
                return Arrow(baseNumber, result, arrows - 1);
            }
        }

        private static BigInteger Power(BigInteger number, BigInteger power)
        {
            int x = number;
            for (int i = 0; i < (power - 1); i++)
            {
                x *= number;
            }
            return x;
        }
    }

Я придумал способ использовать BigInteger.Pow()функция. Это может показаться немного странным, но это потому, что C# BigInterger.Pow(x, y)принимает только int для y, а у teterations есть ОГРОМНЫЕ показатели. Мне пришлось "перевернуть сценарий" и преобразовать x^y = y^x для этого конкретного случая. Я не добавлял никакой проверки ошибок, и он ожидает, что все числа будут положительными целыми числами.

Я знаю, что это работает для x^^2 и x^^3. Я также знаю, что это работает для 2^^4 и 2^^5. У меня нет вычислительной мощности / памяти / математических знаний, чтобы знать, работает ли это для каких-либо других чисел. 2^^4 и 2 ^^ 5 были единственными, которые я мог проверить и протестировать. Это может сработать для других номеров, но я не смог это подтвердить.

int baseNum = 4;
int exp = 3;
// this example is 4^^3
BigInteger bigAnswer = tetration(baseNum, exp);

// Here is what the method that "does the work" looks like.  

    // This looks a little odd but that is because I am using BigInteger.Pow(x,y)
    // Unfortunately, y can only be an int.  Tetrations have huge exponents, so I had to figure out a
    // way to have x^y work as y^x for this specific application
    // no error checking in here, and it expects positive ints only
    // I *know* this works for x^^2, x^^3, but I don't know if it works for
    // any other number than 2 at ^^4 or higher
    public static BigInteger tetration(int baseNum, int exp)
    {
        if (exp > 2)
        {
            exp = (int)Math.Pow(baseNum, (exp - 3));
        }
        else
        {
            exp = exp - 2;
        }

        Func<BigInteger, int, BigInteger> bigPowHelper = (x, y) => BigInteger.Pow(x, y);
        BigInteger bigAnswer = baseNum;

        for (int i = 0; i < Math.Pow(baseNum, exp); i++)
        {
            bigAnswer = bigPowHelper(bigAnswer, baseNum);
        }
        return bigAnswer;
    }
Другие вопросы по тегам