Самый быстрый способ вычислить десятичную длину целого числа? (.NET)

Помните, JavaScript передает объекты по ссылке. resultHead.next = head означает изменение resultHead.next изменяет head внешне. Вы устанавливаете slow и fast на resultHead, поэтому изменение slow.next изменяет head.

, т.е.

slow === resultHead
resultHead.next === head
slow.next === head
17
задан MichaelGG 24 March 2009 в 23:35
поделиться

9 ответов

Два предложения:

  1. Профиль и помещенный общие падежи сначала.
  2. Сделайте двоичный поиск для уменьшения количества comparions в худшем случае. Можно решить среди 8 альтернатив, использующих точно три сравнения.

Эта комбинация, вероятно, не покупает Вас очень, если распределение не является очень скосом.

6
ответ дан 30 November 2019 в 14:29
поделиться

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

int base10len(uint64_t n) {
  int len = 0;
  /* n < 10^32 */
  if (n >= 10000000000000000ULL) { n /= 10000000000000000ULL; len += 16; }
  /* n < 10^16 */
  if (n >= 100000000) { n /= 100000000; len += 8; }
  /* n < 100000000 = 10^8 */
  if (n >= 10000) { n /= 10000; len += 4; }
  /* n < 10000 */
  if (n >= 100) { n /= 100; len += 2; }
  /* n < 100 */
  if (n >= 10) { return len + 2; }
  else         { return len + 1; }
}

Я сомневаюсь, что это будет немного быстрее, чем, что Вы уже делаете. Но это предсказуемо.

2
ответ дан 30 November 2019 в 14:29
поделиться

Вы прокомментировали в коде, что 10 цифр или больше являются очень редкими, таким образом, Ваше исходное решение не плохо

0
ответ дан 30 November 2019 в 14:29
поделиться

Я сделал некоторое тестирование, и это, кажется, в 2-4 раза быстрее, чем код, который Вы имеете теперь:

static int getLen(long x) {
    int len = 1;
    while (x > 9999) {
        x /= 10000;
        len += 4;
    }
    while (x > 99) {
        x /= 100;
        len += 2;
    }
    if (x > 9) len++;
    return len;
}

Править:
Вот версия, которая использует больше операций Int32, которые должны работать лучше, если у Вас нет x64 приложения:

static int getLen(long x) {
    int len = 1;
    while (x > 99999999) {
        x /= 100000000;
        len += 8;
    }
    int y = (int)x;
    while (y > 999) {
        y /= 1000;
        len += 3;
    }
    while (y > 9) {
        y /= 10;
        len ++;
    }
    return len;
}
2
ответ дан 30 November 2019 в 14:29
поделиться

Что Вы подразумеваете под длиной? Количество нулей или всего? Это делает значащие цифры, но Вы в общих чертах понимаете

public static string SpecialFormat(int v, int sf)  
{  
     int k = (int)Math.Pow(10, (int)(Math.Log10(v) + 1 - sf));  
     int v2 = ((v + k/2) / k) * k;  
     return v2.ToString("0,0");  
}
-1
ответ дан 30 November 2019 в 14:29
поделиться

не уверенный, если это быстрее или нет.. но можно всегда рассчитывать...

static int getLen(long x) {
    int len = 1;
    while (x > 0) {
        x = x/10;
        len++
    };
    return len
}
-1
ответ дан 30 November 2019 в 14:29
поделиться

Я не протестировал это, но в законе о переходе к другому основанию говорится:

Log10(x) = Log2(x) / Log2 (10)

Log2 должен быть немного быстрее, чем Log10, если он реализовал право.

0
ответ дан 30 November 2019 в 14:29
поделиться

Из Bit Twiddling Hacks Шона Андерсона :

Найти целочисленную логарифмическую базу 10 целого числа

unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of 
int r;          // result goes here
int t;          // temporary

static unsigned int const PowersOf10[] = 
    {1, 10, 100, 1000, 10000, 100000,
     1000000, 10000000, 100000000, 1000000000};

t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)
r = t - (v < PowersOf10[t]);

Целочисленную логарифмическую базу 10 вычислить сначала используя одну из техник выше для поиска базы журнала 2. По соотношение log10 (v) = log2 (v) / log2 (10), нам нужно умножить его на 1 / log2 (10), что приблизительно равно 1233/4096, или 1233, за которым следует право сдвиг 12. Необходимо добавить еще один потому что IntegerLogBase2 округляет вниз. Наконец, поскольку значение t равно только приблизительное значение, которое может быть отключено на единицу, точное значение находится вычитая результат v < PowersOf10 [t].

Этот метод требует еще 6 операций чем IntegerLogBase2. Это может быть ускорено вверх (на машинах с быстрой памятью доступ), изменив базу журнала 2 метод поиска по таблице выше, чтобы записи содержат то, что вычислено для t (то есть pre-add, -mulitply и -сдвиг). Для этого потребуется всего 9 операций, чтобы найти логическая основа 10, при условии, что 4 таблицы были (по одному на каждый байт v).

Что касается вычисления IntegerLogBase2, на этой странице представлено несколько альтернатив. Это отличный справочник для всех видов высокооптимизированных операций с целыми числами.

Также существует вариант вашей версии, за исключением того, что он предполагает, что значения (а не логическая база 10 значений) равномерно распределены, и, следовательно, имеет экспоненциально упорядоченный поиск:

Найти целое число по базе 10 целого числа очевидным способом

unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of 
int r;          // result goes here

r = (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : 
    (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : 
    (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;

Этот метод хорошо работает, когда ввод равномерно распределяется по 32-битной значения, потому что 76% входов пойманных первым сравнением, 21% пойманные вторым сравнением, 2% поймали третьим и так далее (измельчение оставшегося на 90% при каждом сравнении). Как результат, требуется менее 2,6 операций на в среднем.

5
ответ дан 30 November 2019 в 14:29
поделиться
static int getDigitCount( int x )
    {
    int digits = ( x < 0 ) ? 2 : 1; // '0' has one digit,negative needs space for sign
    while( x > 9 ) // after '9' need more
        {
        x /= 10; // divide and conquer
        digits++;
        }
    return digits;
    }
0
ответ дан 30 November 2019 в 14:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: