0
#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

int main() {
    long long int numb;
    int count;
    cout << "enter number: ";
    cin >> numb;
    int n = 0;
    for (; numb > 0; n++) {
        numb /= 10;
    }

    cout << n << endl;

    int i, digit=0;
    cout << "enter i: ";
    cin >> i;
    digit=  (numb / pow(10, i)) % 10;
    cout << "digit = " << digit;
    return 0;

}

нужно определить, какая цифра стоит в разряде с номером i (разряды нумеруются с конца, т.е. разряд единиц имеет номер 0). в моём случае digit всегда равняется нулю. Как это исправить?

Harry
  • 221,325
voller
  • 43
  • 6
  • 2
    И что, вот это — digit= (numb / pow(10, i)) % 10; — скомпилировалось?... 8-/ – Harry Oct 23 '21 at 14:27
  • 2
    Так Вы ж сами сначала в цикле уменьшаете numb до нуля –  Oct 23 '21 at 14:28
  • я добавил еще одну переменную для numb и digit=(int)(numb/pow(10,i))%10, и всё заработало) спасибо – voller Oct 23 '21 at 14:35

1 Answers1

1
digit=  (numb / pow(10, i)) % 10;
digit = (numb / (long long)pow(10, i)) % 10;

Предупреждение: оказывается, некоторые компиляторы используют функцию pow, вычисляющую подобное возведение в степень неточно, даже несмотря на то, что все точные значения представимы в типе double. Поэтому вместо использования функции pow стоит либо сделать свою функцию, работающую с целыми числами, либо сохранить степени 10 в массив.

А ещё лучше просто делить число на 10 заданное количество раз.

Qwertiy
  • 123,725
  • (long)pow(10, i) А если pow(10, 2) вернёт, например, 99.99..., то отработает ли программа корректно? – wololo Oct 23 '21 at 17:07
  • @wololo, double имеет 53 значащих бита и все числа до 2**53 представляет точно; long long имеет 64 бита, что больше, однако, 10**x = 5**x * 2**x, так что для точного значения достаточно, чтобы 5**x влезло в 53 бита. long может содержать числа до 20 знаков, а log2(5**2) < 47, так что все степени 10, которые помещаются в long, точно представимы и в double. Погрешности вычисления в этом коде не возникнет. – Qwertiy Oct 23 '21 at 17:53
  • @wololo, ну и если хочется убедиться, то for (var x=1n; x<(1n<<64n); x*=10n) if (x !== BigInt(Number(x))) console.log(x); x-=10n; if (x !== BigInt(Number(x))) console.log("DONE"); выводит только DONE. – Qwertiy Oct 23 '21 at 17:59
  • @wololo, ну или вот так: for (var q=0; 10n**BigInt(q) == 10**q; ++q); console.log(q) - получится 23. – Qwertiy Oct 23 '21 at 18:03
  • double имеет 53 значащих бита и все числа до 2**53 представляет точно Это не важно, т.к. ни стандарт IEEE-754, ни стандарт языка C не требуют, чтобы функция pow возвращала точный математический результат, если он (точный математический результат возведения в степень) представим типом double. – wololo Oct 23 '21 at 18:58
  • var q=0; ... 10**q ECMA-262 также не требует, чтобы операция возведения в степень над Number возвращала точный результат. См. описание абстрактной операции Number::exponentiate, через которую определяется семантика оператора ** и Math.pow(): ECMA-262/6.1.6.1.3/13: Return an implementation-approximated value representing the result of raising ℝ(base) to the ℝ(exponent) power.. – wololo Oct 23 '21 at 18:58
  • 1
    Если разработчики JS-движка, либо авторы Сишной версии функции, которую может в своих недрах вызывать движок, подошли основательно к реализации операции возведения в степень, то конечно можно получить корректный результат, но никаких гарантий нет, и если хочется убедиться, то: 1, 2, 3. – wololo Oct 23 '21 at 18:58
  • @wololo, да, неожиданно... Получается, в рандомных версиях некоторых компиляторах pow почему-то работает не так, как в других версиях, и не так, как в js? Я думал, что с одним и тем же типом везде должно работать одинаково... – Qwertiy Oct 23 '21 at 19:08
  • @wololo, добавил предупреждение в ответ. – Qwertiy Oct 23 '21 at 19:13