найти "длину строки" int - PullRequest
6 голосов
/ 10 ноября 2010

В основном я хочу вернуть количество цифр в int -> значения, подобные этому:

(int)1 => 1
(int)123 => 3
(int)12345678 => 8

Я ничего не знаю о С, поэтому, пожалуйста, потерпите меня. Я знаю цель c, но я использую int и float вместо NSNumbers. Я понимаю, что могу преобразовать целые числа в объективные объекты c, но это кажется странным, и если я смогу сделать это с помощью C, я буду знать это в будущем.

Спасибо

Ответы [ 6 ]

23 голосов
/ 10 ноября 2010

использование

int d = (value == 0 ? 1 : (int)(log10(value)+1));

Обратите внимание, что это не работает для отрицательных чисел, вам придется использовать

int d = (value == 0 ? 1 : ((int)(log10(fabs(value))+1) + (value < 0 ? 1 : 0)));

, который добавляет 1 к знаку минус, если value отрицательно.

12 голосов
/ 10 ноября 2010

Вероятно, намного быстрее, чем при использовании преобразования журнала или преобразования строки в строку и без использования каких-либо библиотечных функций, это:

int nDigits(int i)
{
  if (i < 0) i = -i;
  if (i <         10) return 1;
  if (i <        100) return 2;
  if (i <       1000) return 3;
  if (i <      10000) return 4;
  if (i <     100000) return 5;
  if (i <    1000000) return 6;      
  if (i <   10000000) return 7;
  if (i <  100000000) return 8;
  if (i < 1000000000) return 9;
  return 10;
}

РЕДАКТИРОВАТЬ после того, как Джефф Йейтс обеспокоен:

Для тех, кто беспокоится о размерах int, отличных от 32-битных (аналогично решению pmg, но все же быстрее, потому что умножение быстрее деления: -)

#include <limits.h>

#define PO10_LIMIT (INT_MAX/10)


int nDigits(int i)
{
  int n,po10;

  if (i < 0) i = -i;
  n=1;
  po10=10;
  while(i>=po10)
  {
    n++;
    if (po10 > PO10_LIMIT) break;
    po10*=10;
  }
  return n;
}
5 голосов
/ 10 ноября 2010

Вот еще один вариант

int nDigits(unsigned i) {
    int n = 1;
    while (i > 9) {
        n++;
        i /= 10;
    }
    return n;
}

Это быстрее, чем при использовании log10, но медленнее, чем у Керда с каскадными тестами.Однако он не предполагает, что int 32-битные: -)

5 голосов
/ 10 ноября 2010

Используйте логарифмы базы 10:

int length = (int)floor(log10((float)number)) + 1; // works for >0
2 голосов
/ 10 ноября 2010

Более общее решение, особенно если вы хотите узнать длину для целей печати с printf() вариантами:

snprintf(NULL, 0, "%d", myint);

Возвращаемое значение должно указывать длину строки, которая будет напечатана.

1 голос
/ 24 марта 2016

Если ваше целочисленное значение (например, 12345678u) является константой времени компиляции, вы можете позволить компилятору определить для вас длину:

template<typename T>
constexpr unsigned int_decimal_digits(T value)
{
    return (    value / 10
                    ?   int_decimal_digits<T>(value/10) + 1
                    :   1 );
}

Использование:

unsigned n = int_decimal_digits(1234); 
// n = 4

#include <limits.h>
unsigned m = int_decimal_digits(ULLONG_MAX);
// m = maximum length of a "long long unsigned" on your platform

Таким образом, компилятор будет автоматически вычислять количество десятичных разрядов и заполнять значение как константу.Это должно быть самое быстрое из возможных решений, поскольку не требуется вычислений во время выполнения и целочисленные константы обычно вводятся в коды операций команд.(Это означает, что они перемещаются по конвейеру команд, а не по памяти / кешу данных.) Однако для этого требуется компилятор, поддерживающий C ++ 11.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...