Как посчитать десятичные цифры целого числа? - PullRequest
1 голос
/ 26 мая 2020

Я написал программу для определения количества цифр в числе

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    long long num1 = 1999999999999999;
    long long num2 = 9999999999999999;
    int number_of_digit_1 = log10(num1) + 1;
    int number_of_digit_2 = log10(num2) + 1;
    cout << number_of_digit_1 << endl;
    cout << number_of_digit_2 << endl;
}

Результат:

16 
17

Хотя он должен напечатать то же самое число (16). Почему это происходит?

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

log10 принимает различные типы с плавающей запятой в качестве аргументов и возвращает тот же тип в своем результате. В вашем случае он преобразуется в double.

double имеет только 53 бит для целой (значащей) части.

9999999999999999 требуется 54 бита для точного представления .

Когда вы конвертируете 9999999999999999 в double, вы получаете 10000000000000000, так что результат 16 из log10(9999999999999999) вполне ожидаем.

Чтобы получить точное (и возможно быстрее) подсчет цифр в целом числе, вы должны использовать целочисленный метод для вычисления цифр. Существуют различные методы, например Какой самый быстрый метод вычисления целого Log10 для 64-битных целых чисел на современных x86-64? или http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog

0 голосов
/ 26 мая 2020

log10(long long int) не определено. Затем num2 неявно преобразуется в double, что имеет меньшую точность. Преобразование num2 в long double решает проблему.

Этот обходной путь не работает с Visual Studio (там double = long double). Однако он работает с g cc и clang.

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    long long num1 = 1999999999999999;
    long long num2 = 9999999999999999;
    long double x = static_cast<long double> (num2);
    int number_of_digit_1 = log10(num1) + 1;
    int number_of_digit_2 = log10(num2) + 1;
    int number_of_digit_3 = log10(x) + 1;
    cout << number_of_digit_1 << endl;
    cout << number_of_digit_2 << endl;
    cout << number_of_digit_3 << endl;
}

Другая возможность - использовать простую специальную функцию для вычисления количества цифр с простым while l oop. Как правило, в такой ситуации не стоит беспокоиться о высоком КПД.

template <typename T> 
int n_digits (T num) {
    int n = 0;
    while (num != 0) {
        ++n;
        num /= 10;
    }
    return n;
}
...