Подтвердить что ты не робот

Почему я не могу хранить свои данные в длинном типе данных?

int power(int first,int second) {
    int counter1 = 0;
    long ret = 1;

    while (counter1 != second){
        ret *= first;
        counter1 += 1;
    }
    return ret;
}


int main(int argc,char **argv) {

    long one = atol(argv[1]);
    long two = atol(argv[2]);
    char word[30];
    long finally;

    printf("What is the operation? 'power','factorial' or 'recfactorial'\n");
    scanf("%20s",word);

    if (strcmp("power",word) == 0){
        finally = power(one,two);
        printf("%ld\n",finally);
        return 0;
    } 

}

Эта функция предназначена для работы "мощности", как на калькуляторе, поэтому, если я пишу: ./a.out 5 3, она даст мне 5 мощности 3 и распечатайте 125

Проблема в том, что числа, подобные цифрам: ./a.out 20 10, 20 - мощность 10, я ожидаю увидеть результат: 1.024 x 10^13, но вместо этого выводит 797966336.

В чем причина текущего вывода, который я получаю?

Примечание. Я предполагаю, что это имеет какое-то отношение к типам данных atol() и long. Являются ли они недостаточно большими для хранения информации? Если нет, любая идея, как заставить его работать для больших чисел?

4b9b3361

Ответ 1

Конечно, ваши входы long, но ваша функция power принимает и возвращает int! По-видимому, это 32-бит в вашей системе & hellip; поэтому в вашей системе 1,024 & times; 10 13 больше, чем int может обрабатывать.

Убедитесь, что вы выбрали тип, который достаточно велик для ваших данных, и используйте его последовательно. Даже long может быть недостаточно. проверьте свою систему!

Ответ 2

Прежде всего вам нужно изменить тип возвращаемого типа и ввести типы параметров power() от int до long. В противном случае, в системе, где long и int имеют разный размер,

  • Входные аргументы могут быть усечены до int, пока вы проходите long.

  • Возвращаемое значение будет возвращено до int перед возвратом, что может урезать фактическое значение.

После этого 1.024 × 10 13 (10240000000000) не может удерживаться символом int или long (если 32 бита). Вам нужно использовать тип данных с большей шириной, например long long.

Ответ 3

один и два длинны.

long one = atol(argv[1]);
long two = atol(argv[2]);

Вы вызываете эту функцию с ними

int power(int first, int second);

Но ваша функция принимает int, здесь подразумевается неявное преобразование и возвращает int. Итак, ваши длинные int, которые вызывают поведение undefined (см. Комментарии).

Ответ 4

Быстрый ответ:

Значения вашей функции power неявно преобразуются.

Измените параметры функции, чтобы ввести другой, а затем int, который может содержать большие значения, одним возможным типом будет long.

  • Входное значение получает тип, преобразованный и усеченный, чтобы соответствовать параметрам вашей функции.

  • Результат вычисления в теле функции будет снова преобразован в соответствие с типом возвращаемого значения, в вашем случае int: не может обрабатывать размер значений.

Примечание 1: как отмечают более опытные участники, существует проблема с машиной, которая заключается в том, что ваш тип int не обрабатывает обычный размер int, который должен обрабатывать,


1. Чтобы сделать ответ полным

Ответ 5

Код смешивает int, long и надеется, что ответ превысит диапазон long.

Ответ - это просто результат попыток положить 10 фунтов картофеля в 5-фунтовый мешок.


... идея, как заставить его работать для больших чисел.

  • Используйте самое широкое целое число. Примеры: uintmax_t, unsigned long long.

С C99 вперед обычно наибольшее представимое целое число будет UINTMAX_MAX.

#include <stdint.h>

uintmax_t power_a(long first, long second) {
  long counter1 = 0;
  uintmax_t ret = 1;

  while (counter1 != second){  // number of iterations could be in the billions
    ret *= first;
    counter1 += 1;
  }
  return ret;
}

Но давайте избежим проблемного поведения с отрицательными числами и повысим эффективность расчета от линейного к экспоненциальному.

// return x raised to the y power
uintmax_t pow_jululu(unsigned long x, unsigned long y) {
  uintmax_t z = 1;
  uintmax_t base = x;
  while (y) {   // max number of iterations would bit width: e.g. 64
    if (y & 1) {
      z *= base;
    }
    y >>= 1;
    base *= base;
  }
  return z;
}

int main(int argc,char **argv) {
    assert(argc >= 3);
    unsigned long one = strtoul(argv[1], 0, 10);
    unsigned long two = strtoul(argv[2], 0, 10);
    uintmax_t finally = pow_jululu(one,two);
    printf("%ju\n",finally);
    return 0;
}

Этот подход также имеет пределы. 1) z *= base может математически переполняться для вызовов типа pow_jululu(2, 1000). 2) base*base может математически переполняться в необычной ситуации, когда unsigned long больше половины ширины uintmax_t. 3) некоторые другие нюансы тоже.

  1. Курорт для других типов, например: long double, Арифметика с произвольной точностью. Это, вероятно, выходит за рамки этой простой задачи.

Ответ 6

Вы можете использовать длинный длинный 8 байтов в длину вместо 4-байтовой длины long и int.

long long предоставит вам значения от -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807. Это, я думаю, должно охватывать все значения, с которыми вы можете столкнуться только сейчас.