Однажды я задал связанный вопрос: как вы можете получить первую цифру в int? Многие из тех же методологий, что и ниже, были использованы в ответах людей. Вот ссылка на случай, если она имеет отношение к вашей задаче [ stackoverflow.com/questions/701322/]
Dinah
Подходит ли встроенная сборка?
György Andrasek
1
Хотя все эти ответы относятся к основанию 10, его довольно легко изменить, чтобы вычислить результат для любой желаемой базы.
Ира Бакстер
Ответы:
106
Ну, самый эффективный способ, предполагая, что вы знаете размер целого числа, это поиск. Должен быть быстрее, чем подход, основанный на гораздо более коротком логарифме. Если вам не нужно считать «-», удалите + 1.
// generic solutiontemplate<class T>int numDigits(T number){int digits =0;if(number <0) digits =1;// remove this line if '-' counts as a digitwhile(number){
number /=10;
digits++;}return digits;}// partial specialization optimization for 32-bit numberstemplate<>int numDigits(int32_t x){if(x == MIN_INT)return10+1;if(x <0)return numDigits(-x)+1;if(x >=10000){if(x >=10000000){if(x >=100000000){if(x >=1000000000)return10;return9;}return8;}if(x >=100000){if(x >=1000000)return7;return6;}return5;}if(x >=100){if(x >=1000)return4;return3;}if(x >=10)return2;return1;}// partial-specialization optimization for 8-bit numberstemplate<>int numDigits(char n){// if you have the time, replace this with a static initialization to avoid// the initial overhead & unnecessary branchstaticchar x[256]={0};if(x[0]==0){for(char c =1; c !=0; c++)
x[c]= numDigits((int32_t)c);
x[0]=1;}return x[n];}
Наверное, быстрее, чем мой ответ, молодец. Для повышения эффективности, если вы знаете, что ваши входные числа будут в основном небольшими (я предполагаю, что их меньше 100 000), то поменяйте местами тесты: if (x <10) return 1; if (x <100) возвращает 2; и т.д., чтобы функция выполняла меньше тестов и быстрее выходила.
squelart
29
Или, возможно, измените порядок и вложите операторы if, чтобы выполнить бинарный поиск вместо линейного поиска.
dave4420,
1
Это не очень хорошая идея. Что происходит, когда архитектура расширяется до 256-битных целых чисел. Вы должны помнить, чтобы вернуться и изменить этот код. В реальной жизни этого не произойдет, и, скорее всего, это будет использоваться для создания буфера правильного размера, который вы сейчас открываете себе для всех видов проблем с переполнением буфера на больших архитектурах.
Мартин Йорк,
3
при условии равномерного распределения чисел обратный линейный поиск (начиная с макс. цифр до 1) может быть в среднем быстрее, чем бинарный поиск, поскольку чисел с N цифрами значительно больше, чем с N-1 цифрами graphics.stanford.edu/~ Сеандер /…
фа.
6
Я бы не стал сильно беспокоиться о 256 или 128 битных целых числах. Если вам не нужно посчитать количество электронов во Вселенной (10 ^ 78 в прошлый раз, когда я это делал), 64 бита будут работать довольно хорошо. 32-битные машины просуществовали ~ ~ 15 лет. Я предполагаю, что 64-битные машины будут работать намного дольше. Для больших чисел подойдет многоточная арифметика, и я сомневаюсь, что эффективность подсчета цифр будет иметь значение.
Ира Бакстер
74
Самый простой способ это сделать:
unsignedGetNumberOfDigits(unsigned i){return i >0?(int) log10 ((double) i)+1:1;}
log10 определяется в <cmath>или <math.h>. Вам нужно будет профилировать это, чтобы увидеть, если это быстрее, чем любой из других, размещенных здесь. Я не уверен, насколько это надежно в отношении точности с плавающей точкой. Кроме того, аргумент не подписан как отрицательные значения, и лог не смешивается.
Для 32-битных и 56-битных операций с плавающей запятой это, вероятно, работает. Если входное значение длинное (64 бита), 56-битовая логарифм с двойной точностью может привести к неправильному ответу в случае значений вблизи больших значений 10 ^ n. Ожидайте неприятности выше 2 ^ 50.
Ира Бакстер
1
Также возникает вопрос, насколько точны функции журнала. Я не проверял, насколько они точны в современных библиотеках, и мне было бы неудобно слепо полагать, что они хороши для одной части из миллиарда.
Дэвид Торнли
@DavidThornley: журнал или другие математические функции являются совершенно точными, если они не указаны в командной строке компилятора. некоторые из них будут преобразованы в встроенные функции x86 во время компиляции. некоторые не существуют и будут расширяться в формулы существующих встроенных функций. Например, если -fpfastвы используете, вы можете увидеть использование SSE instrinsics вместо x87, что дает меньшую гарантию точности IIRC. но по умолчанию нет проблем.
v.oddou
@DavidThornley: это больше, чем точность. Вопрос в том, гарантировано ли или нет, что log10 (10 ^ k) ≥ k для всех соответствующих k. То есть гарантируется, что любая неизбежная ошибка округления идет в правильном направлении. k + eps в результате работает, k - eps нет. И «Совершенно точно» наивно.
gnasher729
1
Тест i> 0 может быть оптимизирован для i> 9
Пэт
60
Возможно, я неправильно понял вопрос, но разве это не так?
Это может или не может быть быстрее, чем подход с развернутым циклом, который я выбрал - вам нужно профилировать разницу (должно быть незначительным в долгосрочной перспективе).
Виталий
Согласитесь, профилирование - это единственный способ узнать наверняка! Я обновил свой ответ этим комментарием, поскольку ответ ce S (log10 ()) Бена С. исчез.
squelart
11
Розыгрыши: Это самый эффективный способ (количество цифр вычисляются во время компиляции):
template<unsignedlonglong N,size_t base=10>struct numberlength
{enum{ value =1+ numberlength<N/base, base>::value };};template<size_t base>struct numberlength<0, base>{enum{ value =0};};
Может быть полезно определить ширину, необходимую для числового поля при форматировании, элементах ввода и т. Д.
Во-первых, ваше решение не работает для 0. Во-вторых, ваше решение неприменимо к общему случаю переменной. В-третьих, если вы используете постоянный литерал, вы уже знаете, сколько у него цифр.
Виталий
Это работает для 0 тоже. Это также работает для любой базы. Остальные действительные моменты, которые я уже изложил.
blinnov.com
3
Я не думаю, что это на самом деле. Он не работает, 0а также не работает на базе 1:) и дает деление на ноль ошибок, если база задана как 0. Это может быть исправлено, хотя. В любом случае, я придираюсь к очень старому посту, так что извините, просто я думаю, что это не должно быть шуткой и может быть действительно полезным.
TJM
9
См. Bit Twiddling Hacks для более короткой версии ответа, который вы приняли. Преимущество также заключается в том, что вы можете быстрее найти ответ, если ваш входной сигнал обычно распределяется, сначала проверяя большие константы. (v >= 1000000000)ловит 76% значений, поэтому проверка, что первый будет в среднем быстрее.
Неясно, происходит ли на самом деле быстрое переключение битов. Даже в наихудшем случае мой модифицированный подход требует 4 сравнений (возможно, я смогу уменьшить его до 3, если я рассмотрю разделение дальше, хотя это выглядит маловероятным). Я серьезно сомневаюсь, что это побьет арифметические операции + загрузки памяти (хотя при достаточном доступе они исчезают в кэше процессора). Помните, что в приведенном ими примере они также скрывают базу журналов 2 как некую абстрактную функцию IntegerLogBase2 (которая сама по себе недешева).
Виталий
Так же, как продолжение, да, если числа нормально распределены, проверка порядка выполняется быстрее. Тем не менее, он имеет вырожденный случай быть в два раза медленнее в худшем случае. Разделенный подход по количеству цифр вместо пространства ввода означает, что поведение не имеет вырожденного случая и всегда работает оптимально. Кроме того, помните, что вы предполагаете, что числа будут распределены равномерно. На самом деле, они более склонны следовать некоторым распределением , связанные с <a href=" en.wikipedia.org/wiki/...> будет моя догадка.
Виталий
Взломанные бит-хедлеры не быстрее, чем описанный выше метод разбиения, но они потенциально интересны, если у вас есть более общий случай, такой как float.
Корвин Джой
1
Немного взлома предлагает способ получить int log10, учитывая int log2. Он предлагает несколько способов получить int log2, в основном с использованием нескольких сравнений / ветвей. (Я думаю, что вы недооцениваете стоимость непредсказуемых веток, Виталий). Если вы можете использовать встроенный x86 asm, инструкция BSR даст вам int log2 значения (т. Е. Битовый индекс старшего значащего установленного бита). Это немного медленно на K8 (задержка 10 циклов), но быстро на Core 2 (задержка 2 или 3 цикла). Даже на K8 вполне может быть быстрее, чем сравнения.
Питер Кордес
На K10 lzcnt считает начальные нули, поэтому он почти такой же, как bsr, но ввод 0 больше не является особым случаем с неопределенными результатами. Задержки: BSR: 4, LZCNT: 2.
Питер Кордес
8
преобразовать в строку, а затем использовать встроенные функции
Хотя это эффективно с точки зрения LOC, как отмечено в принятом ответе, использование журнала, вероятно, не даст наилучшей производительности.
Ян
@Ian Почему бы и нет? Это всего лишь пара инструкций FPU. Мили лучше всех веток и петель в других ответах.
маркиз Лорн
5
Предыдущий автор предлагал цикл, который делится на 10. Поскольку умножение на современных машинах происходит намного быстрее, я бы порекомендовал следующий код:
int digits =1, pten=10;while( pten <= number ){ digits++; pten*=10;}
дьявол кроется в деталях - что происходит с скажем std :: numeric_limits <int> :: max == number - может возникнуть проблема с завершением
pgast
2
Если вас беспокоит этот случай, вы можете добавить еще один IF для обработки очень больших значений.
Ира Бакстер
2
Я должен заметить, что на машинах с архитектурой x86 умножение на константу 10, используемое в этом случае, может фактически быть реализовано компилятором как LEA R2, [8 * R1 + R1], ADD R1, R2, так что требуется максимум 2 такта. Умножение на переменные занимает десятки часов, а деление намного хуже.
Ира Бакстер
Преимущество метода деления состоит в том, что вам не нужно беспокоиться об отрицательных числах.
Йоханнес Шауб -
1
Я сравнил подход умножения (с потрясающими, чтобы убрать проблему знака) с подходом деления. На моей машине подход деления на 2 раза медленнее, чем подход умножения. Является ли это преждевременной оптимизацией или нет, зависит от того, где и как это называется.
Spacemoose
5
В архитектуре PPC есть команда подсчета битов. При этом вы можете определить лог-базу 2 положительного целого числа в одной инструкции. Например, 32 бит будет:
#define log_2_32_ppc(x)(31-__cntlzw(x))
Если вы можете обработать небольшую погрешность при больших значениях, вы можете преобразовать ее в log 10 с помощью нескольких инструкций:
Это зависит от платформы и немного неточно, но также не требует ветвлений, деления или преобразования в плавающую точку. Все зависит от того, что вам нужно.
Я знаю только инструкции ppc, но другие архитектуры должны иметь аналогичные инструкции.
Это решение вычисляет log2 (15) = 4 бита и log2 (9) = 4 бита. Но 15 и 9 для печати требуется различное количество десятичных цифр. Так что это не сработает, если только вы не возражаете против того, чтобы ваши цифры иногда печатались слишком много цифр. Но в этом случае вы всегда можете выбрать «10» в качестве ответа для int.
Ира Бакстер
Вау, приблизительная функция. Ницца.
doug65536
4
#include<iostream>#include<math.h>usingnamespace std;int main(){double num;int result;
cout<<"Enter a number to find the number of digits, not including decimal places: ";
cin>>num;
result =((num<=1)?1: log10(num)+1);
cout<<"Number of digits "<<result<<endl;return0;}
Вероятно, это самый простой способ решения вашей проблемы, предполагая, что вы заботитесь только о цифрах перед десятичной дробью, и предполагая, что значение меньше 10 - это всего лишь 1 цифра.
Мне нравится ответ Айры Бакстер. Вот вариант шаблона, который обрабатывает различные размеры и имеет дело с максимальными целочисленными значениями (обновлен, чтобы вывести верхнюю границу из цикла):
#include<boost/integer_traits.hpp>template<typename T> T max_decimal(){
T t =1;for(unsigned i = boost::integer_traits<T>::digits10; i;--i)
t *=10;return t;}template<typename T>unsigned digits(T v){if(v <0) v =-v;if(max_decimal<T>()<= v)return boost::integer_traits<T>::digits10 +1;unsigned digits =1;
T boundary =10;while(boundary <= v){
boundary *=10;++digits;}return digits;}
Чтобы на самом деле получить улучшенную производительность от включения дополнительного теста из цикла, вам нужно специализировать max_decimal (), чтобы возвращать константы для каждого типа на вашей платформе. Достаточно волшебный компилятор может оптимизировать вызов max_decimal () для константы, но специализация лучше для большинства компиляторов сегодня. В настоящее время эта версия, вероятно, медленнее, потому что max_decimal стоит больше, чем тесты, удаленные из цикла.
Я оставлю все это в качестве упражнения для читателя.
Вы хотите, чтобы верхний предел проверял сначала отдельную условную проверку, чтобы не проверять ее на каждой итерации цикла.
Ира Бакстер
Вы не хотите ставить 10 в этот темп. Компилятор может рассмотреть умножение на t как умножение на вещественную переменную и использовать универсальную инструкцию умножения. Если вы вместо этого написали "result * = 10;" компилятор обязательно заметит умножение на константу 10 и выполнит это с несколькими сдвигами и сложениями, что очень быстро.
Ира Бакстер
Если умножение на t всегда было умножением на 10, тогда да, компилятор мог бы сделать уменьшение прочности. Однако в этом случае t не является инвариантным к петле (это всего лишь модификация целочисленной степенной функции, которая у меня лежала). Правильная оптимизация - это специализация на типе, возвращающем константу. Тем не менее, вы правы в том, что в этом случае функция всегда увеличивает число до 10, а не произвольное целое число, а уменьшение силы дает хороший выигрыш. Итак, я внес изменения ... На этот раз дальнейшие изменения действительно остались в качестве упражнения! (Переполнение стека - это большое
времяпровождение
1
#include<stdint.h>// uint32_t [available since C99]/// Determine the number of digits for a 32 bit integer./// - Uses at most 4 comparisons./// - (cX) 2014 adolfo.dimare@gmail.com/// - \see http://stackoverflow.com/questions/1489830/#27669966/** #d == Number length vs Number of comparisons == #c
\code
#d | #c #d | #c
---+--- ---+---
10 | 4 5 | 4
9 | 4 4 | 4
8 | 3 3 | 3
7 | 3 2 | 3
6 | 3 1 | 3
\endcode
*/unsignedNumDigits32bs(uint32_t x){return// Num-># Digits->[0-9] 32->bits bs->Binary Search( x >=100000u// [6-10] [1-5]?// [6-10]( x >=10000000u// [8-10] [6-7]?// [8-10]( x >=100000000u// [9-10] [8]?// [9-10]( x >=1000000000u// [10] [9]?10:9):8):// [6-7]( x >=1000000u// [7] [6]?7:6)):// [1-5]( x >=100u// [3-5] [1-2]?// [3-5]( x >=1000u// [4-5] [3]?// [4-5]( x >=10000u// [5] [4]?5:4):3):// [1-2]( x >=10u// [2] [1]?2:1)));}
Еще один фрагмент кода, который делает то же самое, что и Виталий, но использует бинарный поиск. Массив Powers инициализируется лениво один раз для экземпляра без знака. Перегрузка со знаком типа заботится о знаке минус.
#include<limits>#include<type_traits>#include<array>template<class T>size_tNumberOfDecPositions( T v,typename std::enable_if<std::is_unsigned<T>::value>::type*=0){typedef std::array<T,std::numeric_limits<T>::digits10+1> array_type;static array_type powers_of_10;if( powers_of_10.front()==0){
T n =1;for( T& i: powers_of_10 ){
i = n;
n *=10;}}size_t l =0, r = powers_of_10.size(), p;while( l+1< r ){
p =(l+r)/2;if( powers_of_10[p]<= v )
l = p;else
r = p;}return l +1;};template<class T>size_tNumberOfDecPositions( T v,typename std::enable_if<std::is_signed<T>::value>::type*=0){typedeftypename std::make_unsigned<T>::type unsigned_type;if( v <0)returnNumberOfDecPositions(static_cast<unsigned_type>(-v))+1;elsereturnNumberOfDecPositions(static_cast<unsigned_type>(v));}
Если кого-то волнует дальнейшая оптимизация, обратите внимание, что первый элемент массива полномочий никогда не используется, а lпоявляется +12 раза.
в случае, если необходимо количество цифр И значение каждой позиции цифры, используйте это:
int64_t= number, digitValue, digits =0;// or "int" for 32bitwhile(number !=0){
digitValue = number %10;
digits ++;
number /=10;}
digitдает значение в числовой позиции, которая в настоящее время обрабатывается в цикле. например, для числа 1776 значение цифры:
6 в 1-м цикле
7 во 2-м цикле
7 в 3-м цикле
1 в 4-м цикле
для целого числа 'X' вы хотите знать количество цифр, хорошо, без использования какого-либо цикла, это решение действует только в одной формуле в одной строке, так что это самое оптимальное решение, которое я когда-либо видел для этой проблемы.
int x =1000;
cout<<numberOfDigits =1+floor(log10(x))<<endl ;
Сбой для INT_MAX, а также для отрицательных чисел.
Ран
@ranu Сбой для INT_MAX как? Когда аргумент преобразуется в double? Или вы имеете в виду какой-то невозможный целочисленный ввод с десятичными цифрами INT_MAX? Который также потерпит неудачу при любом другом ответе здесь?
маркиз Лорн
0
int numberOfDigits(int n){if(n<=9){return1;}return1+ numberOfDigits(n/10);}
Это то, что я бы сделал, если вы хотите это для базы 10. Это довольно быстро, и вы, скорее всего, не получите переполнение стека, подсчитывающие целые числа
int num,dig_quant =0;
cout<<"\n\n\t\t--Count the digits in Number--\n\n";
cout<<"Enter Number: ";
cin>>num;for(int i =1; i<=num; i*=10){if(num / i >0){
dig_quant +=1;}}
cout<<"\n"<<number<<" include "<<dig_quant<<" digit"
cout<<"\n\nGoodbye...\n\n";
Если быстрее, тем эффективнее, это улучшение Андрея Александреску . Его версия была уже быстрее, чем наивный путь (деление на 10 на каждую цифру). Приведенная ниже версия имеет постоянное время и быстрее, по крайней мере, для x86-64 и ARM для всех размеров, но занимает в два раза больше двоичного кода, поэтому она не так удобна для кэша.
Я работал над программой, которая требовала, чтобы я проверял, правильно ли пользователь ответил, сколько цифр в числе, поэтому мне пришлось разработать способ проверки количества цифр в целом числе. Это оказалось относительно легко решить.
В конечном итоге это был мой ответ, который в настоящее время работает с числами с менее чем 10 ^ 1000 цифр (можно изменить, изменив значение показателя степени).
PS Я знаю, что этот ответ опоздал на десять лет, но я пришел сюда в 2020 году, чтобы другие могли его использовать.
Конечно, можно использовать любую другую реализацию упорядоченного набора, powers_and_maxи если бы было известно, что кластеризация будет существовать, но не было бы знания о том, где может быть кластер, возможно, лучше всего подойдет саморегулирующаяся реализация дерева.
int numberOfDigits(double number){if(number <0){
number*=-1;}int i=0;while(number > pow(10, i))
i++;
cout <<"This number has "<< i <<" digits"<< endl;return i;}
Ответы:
Ну, самый эффективный способ, предполагая, что вы знаете размер целого числа, это поиск. Должен быть быстрее, чем подход, основанный на гораздо более коротком логарифме. Если вам не нужно считать «-», удалите + 1.
источник
Самый простой способ это сделать:
log10 определяется в
<cmath>
или<math.h>
. Вам нужно будет профилировать это, чтобы увидеть, если это быстрее, чем любой из других, размещенных здесь. Я не уверен, насколько это надежно в отношении точности с плавающей точкой. Кроме того, аргумент не подписан как отрицательные значения, и лог не смешивается.источник
-fpfast
вы используете, вы можете увидеть использование SSE instrinsics вместо x87, что дает меньшую гарантию точности IIRC. но по умолчанию нет проблем.Возможно, я неправильно понял вопрос, но разве это не так?
источник
Примечание: «0» будет иметь 0 цифр! Если вам нужно, чтобы 0 отображало 1 цифру, используйте:
(Спасибо Кевину Фегану)
В конце концов, используйте профилировщик, чтобы узнать, какой из всех ответов здесь будет быстрее на вашем компьютере ...
источник
Розыгрыши: Это самый эффективный способ (количество цифр вычисляются во время компиляции):
Может быть полезно определить ширину, необходимую для числового поля при форматировании, элементах ввода и т. Д.
источник
0
а также не работает на базе1
:) и дает деление на ноль ошибок, если база задана как0
. Это может быть исправлено, хотя. В любом случае, я придираюсь к очень старому посту, так что извините, просто я думаю, что это не должно быть шуткой и может быть действительно полезным.См. Bit Twiddling Hacks для более короткой версии ответа, который вы приняли. Преимущество также заключается в том, что вы можете быстрее найти ответ, если ваш входной сигнал обычно распределяется, сначала проверяя большие константы.
(v >= 1000000000)
ловит 76% значений, поэтому проверка, что первый будет в среднем быстрее.источник
преобразовать в строку, а затем использовать встроенные функции
источник
источник
Предыдущий автор предлагал цикл, который делится на 10. Поскольку умножение на современных машинах происходит намного быстрее, я бы порекомендовал следующий код:
источник
В архитектуре PPC есть команда подсчета битов. При этом вы можете определить лог-базу 2 положительного целого числа в одной инструкции. Например, 32 бит будет:
Если вы можете обработать небольшую погрешность при больших значениях, вы можете преобразовать ее в log 10 с помощью нескольких инструкций:
Это зависит от платформы и немного неточно, но также не требует ветвлений, деления или преобразования в плавающую точку. Все зависит от того, что вам нужно.
Я знаю только инструкции ppc, но другие архитектуры должны иметь аналогичные инструкции.
источник
Вероятно, это самый простой способ решения вашей проблемы, предполагая, что вы заботитесь только о цифрах перед десятичной дробью, и предполагая, что значение меньше 10 - это всего лишь 1 цифра.
источник
Мне нравится ответ Айры Бакстер. Вот вариант шаблона, который обрабатывает различные размеры и имеет дело с максимальными целочисленными значениями (обновлен, чтобы вывести верхнюю границу из цикла):
Чтобы на самом деле получить улучшенную производительность от включения дополнительного теста из цикла, вам нужно специализировать max_decimal (), чтобы возвращать константы для каждого типа на вашей платформе. Достаточно волшебный компилятор может оптимизировать вызов max_decimal () для константы, но специализация лучше для большинства компиляторов сегодня. В настоящее время эта версия, вероятно, медленнее, потому что max_decimal стоит больше, чем тесты, удаленные из цикла.
Я оставлю все это в качестве упражнения для читателя.
источник
источник
Еще один фрагмент кода, который делает то же самое, что и Виталий, но использует бинарный поиск. Массив Powers инициализируется лениво один раз для экземпляра без знака. Перегрузка со знаком типа заботится о знаке минус.
Если кого-то волнует дальнейшая оптимизация, обратите внимание, что первый элемент массива полномочий никогда не используется, а
l
появляется+1
2 раза.источник
в случае, если необходимо количество цифр И значение каждой позиции цифры, используйте это:
digit
дает значение в числовой позиции, которая в настоящее время обрабатывается в цикле. например, для числа 1776 значение цифры:6 в 1-м цикле
7 во 2-м цикле
7 в 3-м цикле
1 в 4-м цикле
источник
источник
источник
для целого числа 'X' вы хотите знать количество цифр, хорошо, без использования какого-либо цикла, это решение действует только в одной формуле в одной строке, так что это самое оптимальное решение, которое я когда-либо видел для этой проблемы.
источник
double
? Или вы имеете в виду какой-то невозможный целочисленный ввод с десятичными цифрами INT_MAX? Который также потерпит неудачу при любом другом ответе здесь?Это то, что я бы сделал, если вы хотите это для базы 10. Это довольно быстро, и вы, скорее всего, не получите переполнение стека, подсчитывающие целые числа
источник
источник
Если быстрее, тем эффективнее, это улучшение Андрея Александреску . Его версия была уже быстрее, чем наивный путь (деление на 10 на каждую цифру). Приведенная ниже версия имеет постоянное время и быстрее, по крайней мере, для x86-64 и ARM для всех размеров, но занимает в два раза больше двоичного кода, поэтому она не так удобна для кэша.
Тесты для этой версии против версии Александра на моей рекламе на фоллике Facebook .
Работает на
unsigned
нетsigned
.источник
Я работал над программой, которая требовала, чтобы я проверял, правильно ли пользователь ответил, сколько цифр в числе, поэтому мне пришлось разработать способ проверки количества цифр в целом числе. Это оказалось относительно легко решить.
В конечном итоге это был мой ответ, который в настоящее время работает с числами с менее чем 10 ^ 1000 цифр (можно изменить, изменив значение показателя степени).
PS Я знаю, что этот ответ опоздал на десять лет, но я пришел сюда в 2020 году, чтобы другие могли его использовать.
источник
где
powers_and_max
у нас(10^n)-1
для всехn
таких, что(10^n) <
std::numeric_limits<type>::max()
и
std::numeric_limits<type>::max()
в массиве:вот простой тест:
Конечно, можно использовать любую другую реализацию упорядоченного набора,
powers_and_max
и если бы было известно, что кластеризация будет существовать, но не было бы знания о том, где может быть кластер, возможно, лучше всего подойдет саморегулирующаяся реализация дерева.источник
эффективный способ
источник
C ++ 11 обновление предпочтительного решения:
предотвращает создание шаблона с помощью double, et. и др.
источник
источник
Это мой способ сделать это:
источник
Вот другой подход:
Это может быть неэффективно, просто что-то отличное от того, что предлагали другие.
источник